blob: b598e2a4dc1e0bca63b77e9ab296316e2b1b2408 [file] [log] [blame]
/**
* @file logger.h
*
* Functions to do logging.
* The macros check whether the logsev is active before evaluating the
* parameters. Use them instead of the functions.
*
* If a log statement ends in a newline, the current log is ended.
* When the log severity changes, an implicit newline is inserted.
*
* @author Ben Gardner
* @license GPL v2+
*/
#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED
#include "logmask.h"
#include <cstring> /* strlen() */
#include <cstdio> /* FILE */
/**
* Initializes the log subsystem - call this first.
* This function sets the log stream and enables the top 3 sevs (0-2).
*
* @param log_file NULL for stderr or the FILE stream for logs.
*/
void log_init(FILE *log_file);
/**
* Show or hide the severity prefix "<1>"
*
* @param true=show false=hide
*/
void log_show_sev(bool show);
/**
* Returns whether a log severity is active.
*
* @param sev The severity
* @return true/false
*/
bool log_sev_on(log_sev_t sev);
/**
* Sets a log sev on or off
*
* @param sev The severity
* @return true/false
*/
void log_set_sev(log_sev_t sev, bool value);
/**
* Sets the log mask
*
* @param mask The mask to copy
*/
void log_set_mask(const log_mask_t& mask);
/**
* Gets the log mask
*
* @param mask Where to copy the mask
*/
void log_get_mask(log_mask_t& mask);
/**
* Logs a string of known length
*
* @param sev The severity
* @param str The pointer to the string
* @param len The length of the string from strlen(str)
*/
void log_str(log_sev_t sev, const char *str, int len);
#define LOG_STR(sev, str, len) \
do { if (log_sev_on(sev)) { log_str(sev, str, len); } } while (0)
#define LOG_STRING(sev, str) \
do { if (log_sev_on(sev)) { log_str(sev, str, strlen(str)); } } while (0)
/**
* Logs a formatted string -- similiar to printf()
*
* @param sev The severity
* @param fmt The format string
* @param ... Additional arguments
*/
void log_fmt(log_sev_t sev, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#ifdef NO_MACRO_VARARG
#define LOG_FMT log_fmt
#else
#define LOG_FMT(sev, args...) \
do { if (log_sev_on(sev)) { log_fmt(sev, ## args); } } while (0)
#endif
/**
* Dumps hex characters inline, no newlines inserted
*
* @param sev The severity
* @param data The data to log
* @param len The number of bytes to log
*/
void log_hex(log_sev_t sev, const void *vdata, int len);
#define LOG_HEX(sev, ptr, len) \
do { if (log_sev_on(sev)) { log_hex(sev, ptr, len); } } while (0)
/**
* Logs a block of data in a pretty hex format
* Numbers on the left, characters on the right, just like I like it.
*
* "nnn | XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX | ................"
* 0 ^6 54^ ^56 72^
*
* nnn is the line number or index/16
*
* @param sev The severity
* @param data The data to log
* @param len The number of bytes to log
*/
void log_hex_blk(log_sev_t sev, const void *data, int len);
#define LOG_HEX_BLK(sev, ptr, len) \
do { if (log_sev_on(sev)) { log_hex_blk(sev, ptr, len); } } while (0)
/**
* Returns the HEX digit for a low nibble in a number
*
* @param nibble The nibble
* @return '0', '1', '2', '3', '4', '5', '6', '7',
* '8', '9', 'a', 'b', 'c', 'd', 'e', or 'f'
*/
static_inline char to_hex_char(int nibble)
{
const char *hex_string = "0123456789abcdef";
return(hex_string[nibble & 0x0F]);
}
#ifdef DEBUG
/**
* This should be called as the first thing in a function.
* It uses the log_func class to add an entry to the function log stack.
* It is automatically removed when the function returns.
*/
#define LOG_FUNC_ENTRY() log_func log_fe = log_func(__func__, __LINE__)
/**
* This should be called right before a repeated function call to trace where
* the function was called. It does not add an entry, but rather updates the
* line number of the top entry.
*/
#define LOG_FUNC_CALL() log_func_call(__LINE__)
#else
#define LOG_FUNC_ENTRY()
#define LOG_FUNC_CALL()
#endif
/**
* This class just adds a entry to the top of the stack on construction and
* removes it on destruction.
* RAII for the win.
*/
class log_func
{
public:
log_func(const char *name, int line);
~log_func();
};
void log_func_call(int line);
void log_func_stack(log_sev_t sev, const char *prefix=0, const char *suffix="\n", int skip_cnt=0);
#define log_func_stack_inline(_sev) log_func_stack((_sev), " [CallStack:", "]\n", 1)
#endif /* LOGGER_H_INCLUDED */