fix bug in handling of FLOG_MSG_T.src_line (changed from signed to unsigned)
[flog.git] / flog_string.c
blob9547cafadf08595735e7060a108bda5fc8bea6d1
1 //! Output string routines for Flog
3 //! @file flog_string.c
4 //! @author Nabeel Sowan (nabeel.sowan@vibes.se)
5 //!
6 //! To convert flog messages to strings
7 //! internal use only, or when creating flog output function
9 #include "flog_string.h"
11 #ifdef FLOG_CONFIG_STRING_OUTPUT
13 #define _GNU_SOURCE
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
19 #ifdef FLOG_CONFIG_TIMESTAMP
20 #include <time.h>
23 //! Create a string with timestamp in ISO-format
25 //! @param[out] **strp string to set (NULL on error)
26 //! @param[in] ts timestamp
27 //! @retval 0 success
28 int flog_get_str_iso_timestamp(char **strp, const FLOG_TIMESTAMP_T ts)
30 struct tm ts_tm;
31 #ifdef FLOG_CONFIG_TIMESTAMP_USEC
32 ts_tm = *localtime(&ts.tv_sec);
33 if(asprintf(strp,"%04d-%02d-%02d %02d:%02d:%02d.%06d", ts_tm.tm_year+1900, ts_tm.tm_mon+1, ts_tm.tm_mday, ts_tm.tm_hour, ts_tm.tm_min, ts_tm.tm_sec, (int)ts.tv_usec)==-1) {
34 #else //FLOG_CONFIG_TIMESTAMP_USEC
35 ts_tm = *localtime(&ts);
36 if(asprintf(strp,"%04d-%02d-%02d %02d:%02d:%02d", ts_tm.tm_year+1900, ts_tm.tm_mon+1, ts_tm.tm_mday, ts_tm.tm_hour, ts_tm.tm_min, ts_tm.tm_sec)==-1) {
37 #endif //FLOG_CONFIG_TIMESTAMP_USEC
38 *strp=NULL;
39 return(-1);
41 return(0);
43 #endif //FLOG_CONFIG_TIMESTAMP
46 //! Create a string or NULL according to message type
48 //! @param[out] **strp string to set (NULL on error)
49 //! @param[in] type type of message
50 //! @retval 0 success
51 int flog_get_str_msg_type(char **strp, const FLOG_MSG_TYPE_T type)
53 *strp=NULL;
54 switch(type)
56 case FLOG_CRITICAL:
57 if(!(*strp=strdup("Critical")))
58 return(-1);
59 break;
60 case FLOG_ERROR:
61 if(!(*strp=strdup("Error")))
62 return(-1);
63 break;
64 case FLOG_WARNING:
65 if(!(*strp=strdup("Warning")))
66 return(-1);
67 break;
68 case FLOG_NOTIFY:
69 if(!(*strp=strdup("!")))
70 return(-1);
71 break;
72 case FLOG_INFO:
73 break;
74 case FLOG_VERBOSE:
75 break;
76 case FLOG_DEBUG:
77 if(!(*strp=strdup("Debug")))
78 return(-1);
79 break;
80 case FLOG_DEEP_DEBUG:
81 if(!(*strp=strdup("Deep debug")))
82 return(-1);
83 break;
84 default:
85 break;
87 return(0);
91 #ifdef FLOG_CONFIG_MSG_ID_STRINGS
92 extern const char *flog_msg_id_str[];
93 #endif //FLOG_CONFIG_MSG_ID_STRINGS
96 //! Create a string from FLOG_MSG_ID
98 //! @param[out] **strp string to set (NULL on error)
99 //! @param[in] msg_id message ID type
100 //! @retval 0 success
101 int flog_get_str_msg_id(char **strp, const FLOG_MSG_ID_T msg_id)
103 *strp=NULL;
104 if(msg_id==0)
105 return(0);
106 if(msg_id>=FLOG_MSG_ID_AMOUNT_RESERVED_FOR_ERRNO) {
107 #ifdef FLOG_CONFIG_MSG_ID_STRINGS
108 //! @todo we need to run toupper() on the first char of the message (maybe another function?)
109 #ifdef FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
110 if(asprintf(strp,"(%d) %s", msg_id, flog_msg_id_str[msg_id-FLOG_MSG_ID_AMOUNT_RESERVED_FOR_ERRNO])==-1) {
111 *strp=NULL;
112 #else //FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
113 if(!(*strp=strdup(flog_msg_id_str[msg_id-FLOG_MSG_ID_AMOUNT_RESERVED_FOR_ERRNO]))) {
114 #endif //FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
115 #else //FLOG_CONFIG_MSG_ID_STRINGS
116 if(asprintf(strp,"%d", msg_id)==-1) {
117 *strp=NULL;
118 #endif //FLOG_CONFIG_MSG_ID_STRINGS
119 return(-1);
121 } else {
122 //! @todo make thread safe with strerror_r()
123 #ifdef FLOG_CONFIG_ERRNO_STRINGS
124 #ifdef FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
125 if(asprintf(strp,"(%d) %s", msg_id, strerror(msg_id))==-1) {
126 *strp=NULL;
127 #else //FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
128 if(!(*strp=strdup(strerror(msg_id)))) {
129 #endif //FLOG_CONFIG_OUTPUT_SHOW_MSG_ID
130 #else //FLOG_CONFIG_ERRNO_STRINGS
131 if(asprintf(strp,"(%d)", msg_id)==-1) {
132 *strp=NULL;
133 #endif //FLOG_CONFIG_ERRNO_STRINGS
134 return(-1);
137 return(0);
141 #ifdef FLOG_CONFIG_SRC_INFO
142 //! Create a string from flog source info
144 //! @param[out] **strp string to set (NULL on error)
145 //! @param[in] *src_file source file
146 //! @param[in] src_line source line
147 //! @param[in] *src_func source function
148 //! @retval 0 success
149 int flog_get_str_src_info(char **strp, const char *src_file, const uint_fast16_t src_line, const char *src_func)
151 *strp=NULL;
152 if(src_file) {
153 if(src_line) {
154 if(src_func) {
155 if(asprintf(strp,"%s:%d|%s()",src_file,(int)src_line,src_func)==-1) {
156 *strp=NULL;
157 return(-1);
159 } else {
160 if(asprintf(strp,"%s:%d",src_file,(int)src_line)==-1) {
161 *strp=NULL;
162 return(-1);
165 } else {
166 if(src_func) {
167 if(asprintf(strp,"%s|%s()",src_file,src_func)==-1) {
168 *strp=NULL;
169 return(-1);
171 } else {
172 if(!(*strp=strdup(src_file)))
173 return(-1);
176 } else {
177 if(src_line) {
178 if(src_func) {
179 if(asprintf(strp,":%d|%s()",(int)src_line,src_func)==-1) {
180 *strp=NULL;
181 return(-1);
183 } else {
184 if(asprintf(strp,":%d",(int)src_line)==-1) {
185 *strp=NULL;
186 return(-1);
189 } else {
190 if(src_func) {
191 if(asprintf(strp,"%s()",src_func)==-1) {
192 *strp=NULL;
193 return(-1);
195 } else {
196 *strp=NULL;
200 return(0);
202 #endif
205 //! Create a string with message header
207 //! @param[out] **strp string to set (NULL on error)
208 //! @param[in] *p flog message type
209 //! @retval 0 success
210 int flog_get_str_message_header(char **strp, const FLOG_MSG_T *p)
212 *strp=NULL;
213 #ifdef FLOG_CONFIG_TIMESTAMP
214 char *str_timestamp;
215 if(flog_get_str_iso_timestamp(&str_timestamp, p->timestamp))
216 return(-1);
217 #endif
218 #ifdef FLOG_CONFIG_SRC_INFO
219 char *str_src_info;
220 if(flog_get_str_src_info(&str_src_info, p->src_file, p->src_line, p->src_func)) {
221 #ifdef FLOG_CONFIG_TIMESTAMP
222 free(str_timestamp);
223 #endif
224 return(-1);
226 #endif
228 if(p->subsystem) {
229 #ifdef FLOG_CONFIG_SRC_INFO
230 if(str_src_info) {
231 #ifdef FLOG_CONFIG_TIMESTAMP
232 if(str_timestamp) {
233 if(asprintf(strp,"%s %s %s", str_timestamp, str_src_info, p->subsystem)==-1) {
234 free(str_timestamp);
235 free(str_src_info);
236 *strp=NULL;
237 return(-1);
239 free(str_timestamp);
240 } else {
241 #endif
242 if(asprintf(strp,"%s %s", str_src_info, p->subsystem)==-1) {
243 free(str_src_info);
244 *strp=NULL;
245 return(-1);
247 #ifdef FLOG_CONFIG_TIMESTAMP
249 #endif
250 free(str_src_info);
251 } else {
252 #endif
253 #ifdef FLOG_CONFIG_TIMESTAMP
254 if(str_timestamp) {
255 if(asprintf(strp,"%s %s", str_timestamp, p->subsystem)==-1) {
256 free(str_timestamp);
257 *strp=NULL;
258 return(-1);
260 free(str_timestamp);
261 } else {
262 #endif
263 if(!(*strp=strdup(p->subsystem)))
264 return(-1);
265 #ifdef FLOG_CONFIG_TIMESTAMP
267 #endif
268 #ifdef FLOG_CONFIG_SRC_INFO
270 #endif
271 } else {
272 #ifdef FLOG_CONFIG_SRC_INFO
273 if(str_src_info) {
274 #ifdef FLOG_CONFIG_TIMESTAMP
275 if(str_timestamp) {
276 if(asprintf(strp,"%s %s", str_timestamp, str_src_info)==-1) {
277 free(str_timestamp);
278 free(str_src_info);
279 *strp=NULL;
280 return(-1);
282 free(str_timestamp);
283 } else {
284 #endif
285 if(!(*strp=strdup(str_src_info))) {
286 free(str_src_info);
287 return(-1);
289 #ifdef FLOG_CONFIG_TIMESTAMP
291 #endif
292 free(str_src_info);
293 } else {
294 #endif
295 #ifdef FLOG_CONFIG_TIMESTAMP
296 if(str_timestamp) {
297 if(!(*strp=strdup(str_timestamp))) {
298 free(str_timestamp);
299 return(-1);
301 free(str_timestamp);
302 } else {
303 #endif
304 *strp=NULL;
305 #ifdef FLOG_CONFIG_TIMESTAMP
307 #endif
308 #ifdef FLOG_CONFIG_SRC_INFO
310 #endif
312 return(0);
316 //! Create a string with message contents
318 //! @param[out] **strp string to set (NULL on error)
319 //! @param[in] type type of message
320 //! @param[in] msg_id msg ID
321 //! @param[in] *text custom message string
322 //! @retval 0 success
323 int flog_get_str_message_content(char **strp, const FLOG_MSG_TYPE_T type, const FLOG_MSG_ID_T msg_id, const char *text)
325 char *str_type,*str_msg_id;
326 *strp=NULL;
327 if(flog_get_str_msg_type(&str_type,type))
328 return(-1);
329 if(flog_get_str_msg_id(&str_msg_id,msg_id)) {
330 free(str_type);
331 return(-1);
333 if(str_type) {
334 if(str_msg_id) {
335 if(text) {
336 if(asprintf(strp,"%s: %s: %s",str_type,str_msg_id,text)==-1) {
337 free(str_type);
338 free(str_msg_id);
339 *strp=NULL;
340 return(-1);
342 } else {
343 if(asprintf(strp,"%s: %s",str_type,str_msg_id)==-1) {
344 free(str_type);
345 free(str_msg_id);
346 *strp=NULL;
347 return(-1);
350 free(str_msg_id);
351 } else {
352 if(text) {
353 if(asprintf(strp,"%s: %s",str_type,text)==-1) {
354 free(str_type);
355 *strp=NULL;
356 return(-1);
358 } else {
359 if(!(*strp=strdup(str_type))) {
360 free(str_type);
361 return(-1);
365 free(str_type);
366 } else {
367 if(str_msg_id) {
368 if(text) {
369 if(asprintf(strp,"%s: %s",str_msg_id,text)==-1) {
370 free(str_msg_id);
371 *strp=NULL;
372 return(-1);
374 } else {
375 if(!(*strp=strdup(str_msg_id))) {
376 free(str_msg_id);
377 return(-1);
380 free(str_msg_id);
381 } else {
382 if(text) {
383 if(!(*strp=strdup(text)))
384 return(-1);
385 } else
386 *strp=NULL;
389 return(0);
393 //! Create and return a string from FLOG_MSG_T type
395 //! @param[out] **strp string to set (NULL on error)
396 //! @param[in] *p flog message struct
397 //! @retval 0 success
398 int flog_get_str_message(char **strp, const FLOG_MSG_T *p)
400 char *str_msg_header, *str_msg_content;
401 *strp=NULL;
402 if(flog_get_str_message_header(&str_msg_header,p))
403 return(-1);
404 if(flog_get_str_message_content(&str_msg_content, p->type, p->msg_id, p->text)) {
405 free(str_msg_header);
406 return(-1);
408 if(str_msg_header) {
409 if(str_msg_content) {
410 if(asprintf(strp,"[%s] %s\n", str_msg_header, str_msg_content)==-1) {
411 free(str_msg_content);
412 free(str_msg_header);
413 *strp=NULL;
414 return(-1);
416 free(str_msg_content);
417 } else {
418 if(asprintf(strp,"[%s]\n", str_msg_header)==-1) {
419 free(str_msg_header);
420 *strp=NULL;
421 return(-1);
424 free(str_msg_header);
425 } else {
426 if(str_msg_content) {
427 if(asprintf(strp,"%s\n", str_msg_content)==-1) {
428 free(str_msg_content);
429 *strp=NULL;
430 return(-1);
432 free(str_msg_content);
433 } else
434 *strp=NULL;
436 return(0);
441 char * flog_msg_t_to_str(const FLOG_MSG_T *p)
443 char *str,*typestr;
444 typestr=flog_get_msg_type_str(p->type);
445 #ifdef FLOG_CONFIG_TIMESTAMP
446 //! @todo add timestamp support
447 #else
448 #ifdef FLOG_CONFIG_SRC_INFO
449 if((p->subsystem != NULL) && (typestr != NULL))
450 asprintf(&str,"[%s:%d|%s() %s] %s%s\n",p->src_file,(int)p->src_line,p->src_func,p->subsystem,typestr,p->text);
451 else if((p->subsystem != NULL) && (typestr == NULL))
452 asprintf(&str,"[%s:%d|%s() %s] %s\n",p->src_file,(int)p->src_line,p->src_func,p->subsystem,p->text);
453 else if((p->subsystem == NULL) && (typestr != NULL))
454 asprintf(&str,"[%s:%d|%s()] %s%s\n",p->src_file,(int)p->src_line,p->src_func,typestr,p->text);
455 else
456 asprintf(&str,"[%s:%d|%s()] %s\n",p->src_file,(int)p->src_line,p->src_func,p->text);
457 #else
458 if((p->subsystem != NULL) && (typestr != NULL))
459 asprintf(&str,"[%s] %s%s\n",p->subsystem,typestr,p->text);
460 else if((p->subsystem != NULL) && (typestr == NULL))
461 asprintf(&str,"[%s] %s\n",p->subsystem,p->text);
462 else if((p->subsystem == NULL) && (typestr != NULL))
463 asprintf(&str,"%s%s\n",typestr,p->text);
464 else
465 asprintf(&str,"%s\n",p->text);
466 #endif //FLOG_CONFIG_SRC_INFO
467 #endif //FLOG_CONFIG_TIMESTAMP
468 free(typestr);
469 return(str);
473 #endif //FLOG_CONFIG_STRING_OUTPUT