diff options
Diffstat (limited to 'liblog.h')
| -rw-r--r-- | liblog.h | 1583 |
1 files changed, 1583 insertions, 0 deletions
diff --git a/liblog.h b/liblog.h new file mode 100644 index 0000000..5e2fad1 --- /dev/null +++ b/liblog.h @@ -0,0 +1,1583 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBLOG_H +#define LIBLOG_H + +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> + + + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-nonliteral" +# pragma clang diagnostic ignored "-Wpadded" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + + +/** + * Mark the message as incomplete an deferred + * printing until LIBLOG_XLOG_UNCORK is used. + */ +#define LIBLOG_XLOG_CORK 0x0001 + +/** + * Output message printed since the first + * LIBLOG_XLOG_CORK (after the last + * LIBLOG_XLOG_UNCORK if any) as one complete + * message. + */ +#define LIBLOG_XLOG_UNCORK 0x0002 + +/** + * Output a backtrace even if the it is not + * configured that backtraces should be printed + * for the selected log level. + */ +#define LIBLOG_XLOG_BACKTRACE 0x0004 + +/** + * Do not output a backtrace even if the it is + * configured that backtraces should be printed + * for the selected log level. + */ +#define LIBLOG_XLOG_NO_BACKTRACE 0x0008 + +/** + * Do not output any new text (apport from potential + * backtrace); allowing `fmt` to be `NULL`. + */ +#define LIBLOG_XLOG_NO_TEXT 0x0010 + + +/** + * Opaque data type for the internal state + * of a `struct liblog_context` + */ +struct liblog_context_internal_state; + +/** + * Log levels + */ +enum liblog_level { + /** + * System is unusable + */ + LIBLOG_EMERGENCY = 0, + + /** + * Action must be taken immediately + */ + LIBLOG_ALERT = 100, + + /** + * Critical condition + */ + LIBLOG_CRITICAL = 200, + + /** + * Error condition + */ + LIBLOG_ERROR = 300, + + /** + * Warning condition + */ + LIBLOG_WARNING = 400, + + /** + * Normal, but significant, condition + */ + LIBLOG_NOTICE = 500, + + /** + * Informational message + */ + LIBLOG_INFO = 600, + + /** + * Less verbose debug-level message: what is happening on a high level + */ + LIBLOG_TRACE = 700, + + /** + * More verbose debug-level message: detailed information about what is going on + */ + LIBLOG_DEBUG = 800 +}; + +/** + * Log channel types + */ +enum liblog_sink { + /** + * Output to syslog + */ + LIBLOG_SYSLOG, + + /** + * Output to a file descriptor + */ + LIBLOG_FILE, + + /** + * Output to a `FILE` + */ + LIBLOG_STREAM +}; + +/** + * Log output configurations; mapping of log levels to log channels + * + * Destroy with `liblog_destroy_output` if destroying manually + */ +struct liblog_output { + /** + * User defined data + * + * This could for example be a path name to the output + * file so that the application knows which file that + * should be subject to rotation when online log rotation + * is performed + */ + void *userdata; + + /** + * The prefix for each log line + * + * A string where the following special symbols will be replaced + * - %{ltime: %} span that marks formatting of the current local time with strftime(3) + * - %{utime: %} span that marks formatting of the current UTC time with strftime(3) + * - %[nano] the nanoseconds of the current time, printed with 9 digits + * - %[micro] the microseconds of the current time, printed with 6 digits + * - %[milli] the milliseconds of the current time, printed with 3 digits + * - %[centi] the centiseconds of the current time, printed with 2 digits + * - %[deci] the deciseconds of the current time, printed with 1 digit + * - %[function] function where the log message is being printed from + * - %[file] file where the log message is being printed from + * - %[line] line in file where the log message is being printed from + * - %[level] log level for the message rounded down to a predefined value + * (printed as string) + * - %[xlevel] the exact log level for the message, printed as the name of + * of the log level rounded down to a predfined value, followed + * by an adjustment + * - %[tid] the process's thread ID + * - %[pid] the process's thread group ID (process ID) + * - %[ppid] the process's parent process ID + * - %[pgid] the process's process group ID + * - %[sid] the process's session ID + * - %[uid] the real user ID of the process + * - %[euid] the effective user ID of the process + * - %[gid] the real group ID of the process + * - %[egid] the effective group ID of the process + * - %[name] the name of process + * - %[argv0] the value of the global `const char *argv0` + * - %% a literal % + * + * If `NULL`, this with be replace with a default format + */ + const char *prefixfmt; + + /** + * If set `.lowest_verbosity` is treated as set to + * the lowest possible value + */ + unsigned lowest_verbosity_unlimited : 1; + + /** + * If set `.higest_verbosity` is treated as set to + * the highest possible value + */ + unsigned highest_verbosity_unlimited : 1; + + /** + * If set, each log message will be prefixed with + * a backtrace + */ + unsigned use_backtrace : 1; + + unsigned : 0; + + /** + * The lowest log level, in regards to verbosity + * but higest in regard to criticality, for which + * this log output channel shall be used + * + * Must not be greater than `.highest_verbosity` + */ + enum liblog_level lowest_verbosity; + + /** + * The higest log level, in regards to verbosity + * but lowest in regard to criticality, for which + * this log output channel shall be used + * + * Must not be less than `.lowest_verbosity` + */ + enum liblog_level highest_verbosity; + + /** + * The output channel type + */ + enum liblog_sink sink_type; + + /** + * The output channel + */ + union { + /** + * Used when `.sink_type` is `LIBLOG_SYSLOG` + * + * The application is responsible for opening and closing syslog + */ + struct { + /** + * The syslog log level to use + */ + int level; + } syslog; + + /** + * Used when `.sink_type` is `LIBLOG_FILE` + */ + struct { + /** + * The file descriptor to write to + */ + int fd; + + /** + * Whether the library shall close the file descriptor + * when destroying the `struct liblog_output` object + */ + unsigned owns_fd : 1; + } file; + + /** + * Used when `.sink_type` is `LIBLOG_STREAM` + */ + struct { + /** + * The stream to write to + */ + FILE *stream; + + /** + * Whether the library shall close the stream + * when destroying the `struct liblog_output` object + */ + unsigned owns_stream : 1; + } stream; + } sink; +}; + +/** + * Logging configurations and state + * + * Initialise with `liblog_init_context`, and then + * configure output using any of the follow functions: + * - liblog_use_fd + * - liblog_use_fd_for_range + * - liblog_use_file + * - liblog_use_file_for_range + * - liblog_use_stderr + * - liblog_use_stderr_for_range + * - liblog_use_stream + * - liblog_use_stream_for_range + * - liblog_use_syslog + * - liblog_use_syslog_for_range + * - liblog_use_output + * + * Destroy with `liblog_destroy_context` + */ +struct liblog_context { + /** + * Opaque state + */ + struct liblog_context_internal_state *internal_state; + + /** + * Log output configurations; mapping of log levels to log channels + */ + struct liblog_output *outputs; + + /** + * Number of elements in noutputs + */ + size_t noutputs; + + /** + * Mask of log level groups to exclude when logging + */ + unsigned logmask; +}; +/* TODO add multithreading support */ + + + +/* for internal use { */ +#define LIBLOG_VA__(FUNC, ...)\ + int ret;\ + va_list args;\ + va_start(args, fmt);\ + ret = FUNC(__VA_ARGS__, args);\ + va_end(args);\ + return ret + +#define LIBLOG_OUTPUT_UNRANGED__(...)\ + (&(struct liblog_output){\ + .userdata = NULL,\ + .prefixfmt = prefixfmt,\ + .lowest_verbosity_unlimited = 1U,\ + .highest_verbosity_unlimited = 1U,\ + .use_backtrace = (use_backtrace ? 1U : 0U),\ + __VA_ARGS__\ + }) + +#define LIBLOG_OUTPUT_RANGED__(...)\ + (&(struct liblog_output){\ + .userdata = NULL,\ + .prefixfmt = prefixfmt,\ + .lowest_verbosity_unlimited = 0U,\ + .highest_verbosity_unlimited = 0U,\ + .use_backtrace = (use_backtrace ? 1U : 0U),\ + .lowest_verbosity = least_verbose,\ + .highest_verbosity = most_verbose,\ + __VA_ARGS__\ + }) + +#if defined(__clang__) +# define LIBLOG_PRINTF__(FMTIDX) __attribute__((__format__(__printf__, (FMTIDX), (FMTIDX) + 1))) +# define LIBLOG_VPRINTF__(FMTIDX) __attribute__((__format__(__printf__, (FMTIDX), 0))) +#elif defined(__GNUC__) +# define LIBLOG_PRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), (FMTIDX) + 1))) +# define LIBLOG_VPRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), 0))) +#else +# define LIBLOG_PRINTF__(FMTIDX) +# define LIBLOG_VPRINTF__(FMTIDX) +#endif + +#if defined(__GNUC__) +# define LIBLOG_CONST__ __attribute__((__const__)) +#else +# define LIBLOG_CONST__ +#endif + +LIBLOG_CONST__ unsigned liblog_logmask__(enum liblog_level least_verbose, enum liblog_level most_verbose); +/* } */ + + + +/** + * Initialise a `struct liblog_context` + * + * @param ctx That object to initialise + * @return 0 on success, -1 on failure + */ +int liblog_init_context(struct liblog_context *ctx); + +/** + * Destroy a `struct liblog_context` + * + * @param ctx That object to destroy + * @return 0 on success, -1 on failure (object will + * still be completely destroyed) + */ +int liblog_destroy_context(struct liblog_context *ctx); + +/** + * Destroy a `struct liblog_output` + * + * @param output That object to destroy + * @return 0 on success, -1 on failure (object will + * still be completely destroyed) + */ +int liblog_destroy_output(struct liblog_output *output); + + +/** + * Remove log level mask, causing all log messages, that + * have an output configured, to be printed + * + * @param ctx Logging configurations and state + */ +inline void +liblog_clear_mask(struct liblog_context *ctx) +{ if (ctx) ctx->logmask = 0U; } + +/** + * Apply log level mask that is configured in the + * process's environment variable "LIBLOG_LOGMASK" + * + * This is done automatically by `liblog_init_context` + * + * If the LIBLOG_LOGMASK environment variable is + * unset or empty, anything more verbose than a + * some specific level (currently `LIBLOG_WARNING`) + * will be filtered. + * + * @param ctx Logging configurations and state + */ +void liblog_apply_env_mask(struct liblog_context *ctx); + +/** + * Stop log messages within a certain range of + * log levels from being printed + * + * @param ctx Logging configurations and state + * @param least_verbose The lowest (least verbose, most critical) log level + * to filter out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + * @param most_verbose The highest (most verbose, least critical) log level + * to filter out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + * + * This function has no effect if, after rounding, `least_verbose > most_verbose` + */ +inline void +liblog_mask_range(struct liblog_context *ctx, enum liblog_level least_verbose, enum liblog_level most_verbose) +{ if (ctx) ctx->logmask |= liblog_logmask__(least_verbose, most_verbose); } + +/** + * Stop log messages with a certain log level or + * higher (more verbose, less critical) from being printed + * + * @param ctx Logging configurations and state + * @param least The lowest (least verbose, most critical) log level to + * filter out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + */ +inline void +liblog_mask_verbose(struct liblog_context *ctx, enum liblog_level least) +{ liblog_mask_range(ctx, least, LIBLOG_DEBUG); } + +/** + * Stop log messages with a certain log level group + * (all levels up to but excluding the next predefined + * log level) from being printed + * + * @param ctx Logging configurations and state + * @param group The log level to filter out; will be rounded + * up or down (unspecified which) to the closest + * predefined log level value + */ +inline void +liblog_mask_level(struct liblog_context *ctx, enum liblog_level group) +{ liblog_mask_range(ctx, group, group); } + +/** + * Stop filtering out log messages within a certain + * range of log levels from being printed + * + * @param ctx Logging configurations and state + * @param least_verbose The lowest (least verbose, most critical) log level to + * stop filtering out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + * @param most_verbose The highest (most verbose, least critical) log level to + * filtering out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + * + * This function has no effect if, after rounding, `least_verbose > most_verbose` + */ +inline void +liblog_unmask_range(struct liblog_context *ctx, enum liblog_level least_verbose, enum liblog_level most_verbose) +{ if (ctx) ctx->logmask &= ~liblog_logmask__(least_verbose, most_verbose); } + +/** + * Stop filtering out log messages with a certain log level or + * higher (more verbose, less critical) from being printed + * + * @param ctx Logging configurations and state + * @param least The lowest (least verbose, most critical) log level to + * stop filtering out; will be rounded up or down (unspecified + * which) to the closest predefined log level value + */ +inline void +liblog_unmask_verbose(struct liblog_context *ctx, enum liblog_level least) +{ liblog_unmask_range(ctx, least, LIBLOG_DEBUG); } + +/** + * Stop filtering out log messages with a certain log level + * group (all levels up to but excluding the next predefined + * log level) from being printed + * + * @param ctx Logging configurations and state + * @param group The log level to stop filtering out; will be + * rounded up or down (unspecified which) to the + * closest predefined log level value + */ +inline void +liblog_unmask_level(struct liblog_context *ctx, enum liblog_level group) +{ liblog_unmask_range(ctx, group, group); } + + +/** + * Add a log output + * + * @param ctx Logging configurations and state + * @param output The configurations for the additional output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +struct liblog_output *liblog_use_output(struct liblog_context *ctx, const struct liblog_output *output); + +/** + * Set up logging with syslog(3) + * + * @param ctx Logging configurations and state + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @return 0 on success, -1 on failure + * + * This function adds multi new output configurations to `ctx` + */ +int liblog_use_syslog(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace); + +/** + * Set up logging with syslog(3) + * + * @param ctx Logging configurations and state + * @param syslog_level The syslog(3) log level that shall be used + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_syslog_for_range(struct liblog_context *ctx, int syslog_level, const char *prefixfmt, int use_backtrace, + enum liblog_level least_verbose, enum liblog_level most_verbose) +{ return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_SYSLOG, .sink.syslog = {syslog_level})); } + +/** + * Set up logging to a file descriptor + * + * @param ctx Logging configurations and state + * @param fd The file descriptor to log to + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_fd(struct liblog_context *ctx, int fd, const char *prefixfmt, int use_backtrace) +{ return liblog_use_output(ctx, LIBLOG_OUTPUT_UNRANGED__(.sink_type = LIBLOG_FILE, .sink.file = {fd, 0})); } + +/** + * Set up logging to a file descriptor + * + * @param ctx Logging configurations and state + * @param fd The file descriptor to log to + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_fd_for_range(struct liblog_context *ctx, int fd, const char *prefixfmt, int use_backtrace, + enum liblog_level least_verbose, enum liblog_level most_verbose) +{ return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_FILE, .sink.file = {fd, 0})); } + +/** + * Set up logging to an output stream + * + * @param ctx Logging configurations and state + * @param stream The stream to log to + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_stream(struct liblog_context *ctx, FILE *stream, const char *prefixfmt, int use_backtrace) +{ return liblog_use_output(ctx, LIBLOG_OUTPUT_UNRANGED__(.sink_type = LIBLOG_STREAM, .sink.stream = {stream, 0})); } + +/** + * Set up logging to an output stream + * + * @param ctx Logging configurations and state + * @param stream The stream to log to + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_stream_for_range(struct liblog_context *ctx, FILE *stream, const char *prefixfmt, int use_backtrace, + enum liblog_level least_verbose, enum liblog_level most_verbose) +{ return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_STREAM, .sink.stream = {stream, 0})); } + +/** + * Set up logging to a file + * + * @param ctx Logging configurations and state + * @param dirfd File descriptor to the directory `path` is relative to if + * it is a relative path, or -1 to for the path to be absolute, + * failing with EINVAL if it is relative); AT_FDCWD for the + * current working directory + * @param path The path of the file to write to, if `NULL` or `""` + * dirfd will be used as the file descriptor to write to; + * if the file exists, it is opened in append mode, otherwise + * it is created to readable by every user but only writable + * by the current user + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +struct liblog_output *liblog_use_file(struct liblog_context *ctx, int dirfd, const char *path, + const char *prefixfmt, int use_backtrace); + +/** + * Set up logging to a file + * + * @param ctx Logging configurations and state + * @param dirfd File descriptor to the directory `path` is relative to if + * it is a relative path, or -1 to for the path to be absolute, + * failing with EINVAL if it is relative); AT_FDCWD for the + * current working directory + * @param path The path of the file to write to, if `NULL` or `""` + * dirfd will be used as the file descriptor to write to; + * if the file exists, it is opened in append mode, otherwise + * it is created to readable by every user but only writable + * by the current user + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +struct liblog_output *liblog_use_file_for_range(struct liblog_context *ctx, int dirfd, const char *path, + const char *prefixfmt, int use_backtrace, + enum liblog_level least_verbose, enum liblog_level most_verbose); + +/** + * Set up logging to the standard output + * + * @param ctx Logging configurations and state + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_stderr(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace) +{ return liblog_use_fd(ctx, 2, prefixfmt, use_backtrace); } + +/** + * Set up logging to the standard output + * + * @param ctx Logging configurations and state + * @param prefixfmt See `.prefixfmt` in `struct liblog_output` + * @param use_backtrace Whether each log message should be prefix with a log backtrace + * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), + * inclusive bound for the range liblog log level for which log + * messages should be output to the new output + * @return The new output configuration (this is an object + * owned by `ctx` and should not be deallocated, + * it is returned so that changes can be made) + * on success, `NULL` on failure + */ +inline struct liblog_output * +liblog_use_stderr_for_range(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace, + enum liblog_level least_verbose, enum liblog_level most_verbose) +{ return liblog_use_fd_for_range(ctx, 2, prefixfmt, use_backtrace, least_verbose, most_verbose); } + + +/** + * Write a log message with a custom log level + * + * This function's behaviour is customisable + * using its `flags` parameter + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param flags Modifications the the function's behaviour; + * may be 0 or the OR of any of the following values: + * - LIBLOG_XLOG_CORK: + * Mark the message as incomplete an deferred + * printing until LIBLOG_XLOG_UNCORK is used. + * - LIBLOG_XLOG_UNCORK: + * Output message printed since the first + * LIBLOG_XLOG_CORK (after the last + * LIBLOG_XLOG_UNCORK if any) as one complete + * message. + * - LIBLOG_XLOG_BACKTRACE: + * Output a backtrace even if the it is not + * configured that backtraces should be printed + * for the selected log level. + * - LIBLOG_XLOG_NO_BACKTRACE: + * Do not output a backtrace even if the it is + * configured that backtraces should be printed + * for the selected log level. + * - LIBLOG_XLOG_NO_TEXT: + * Do not output any new text (apport from potential + * backtrace); allowing `fmt` to be `NULL`. + * However, LIBLOG_XLOG_CORK and LIBLOG_XLOG_UNCORK + * cannot be combined, nor can LIBLOG_XLOG_BACKTRACE + * and LIBLOG_XLOG_NO_BACKTRACE be combined + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(4) int +liblog_vxlog(struct liblog_context *ctx, enum liblog_level level, unsigned flags, const char *fmt, va_list args); + +/** + * Write a log message with a custom log level + * + * This function's behaviour is customisable + * using its `flags` parameter + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param flags Modifications the the function's behaviour; + * may be 0 or the OR of any of the following values: + * - LIBLOG_XLOG_CORK: + * Mark the message as incomplete an deferred + * printing until LIBLOG_XLOG_UNCORK is used + * - LIBLOG_XLOG_UNCORK: + * Output message printed since the first + * LIBLOG_XLOG_CORK (after the last + * LIBLOG_XLOG_UNCORK if any) as one complete + * message + * - LIBLOG_XLOG_BACKTRACE: + * Output a backtrace even if the it is not + * configured that backtraces should be printed + * for the selected log level + * - LIBLOG_XLOG_NO_BACKTRACE: + * Do not output a backtrace even if the it is + * configured that backtraces should be printed + * for the selected log level + * - LIBLOG_XLOG_NO_TEXT: + * Do not output any new text (apport from potential + * backtrace); allowing `fmt` to be `NULL`. + * However, LIBLOG_XLOG_CORK and LIBLOG_XLOG_UNCORK + * cannot be combined, nor can LIBLOG_XLOG_BACKTRACE + * and LIBLOG_XLOG_NO_BACKTRACE be combined + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(4) inline int +liblog_xlog(struct liblog_context *ctx, enum liblog_level level, unsigned flags, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vxlog, ctx, level, flags, fmt); } + + +/** + * If there is an incomplete log message being constructed, + * terminate it and print it + * + * @param ctx Logging configurations and state + * @return 0 on success, -1 on failure + * + * @seealso liblog_xlog + * @seealso liblog_dump_backtrace_cork + * @seealso liblog_log_cork + * @seealso liblog_log_no_backtrace_cork + * @seealso liblog_emergency_cork + * @seealso liblog_alert_cork + * @seealso liblog_critical_cork + * @seealso liblog_error_cork + * @seealso liblog_warning_cork + * @seealso liblog_notice_cork + * @seealso liblog_info_cork + * @seealso liblog_trace_cork + * @seealso liblog_debug_cork + */ +inline int +liblog_uncork(struct liblog_context *ctx) +{ return liblog_xlog(ctx, 0, LIBLOG_XLOG_NO_BACKTRACE | LIBLOG_XLOG_NO_TEXT | LIBLOG_XLOG_UNCORK, NULL); } + + +/** + * Write the backtrace as a log message with a custom log level + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @return 0 on success, -1 on failure + */ +inline int +liblog_dump_backtrace(struct liblog_context *ctx, enum liblog_level level) +{ return liblog_xlog(ctx, level, LIBLOG_XLOG_BACKTRACE | LIBLOG_XLOG_NO_TEXT, NULL); } + +/** + * Write the backtrace as a log message with a custom log level + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * The backtrace will be terminated by a new line + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @return 0 on success, -1 on failure + */ +inline int +liblog_dump_backtrace_cork(struct liblog_context *ctx, enum liblog_level level) +{ return liblog_xlog(ctx, level, LIBLOG_XLOG_BACKTRACE | LIBLOG_XLOG_NO_TEXT | LIBLOG_XLOG_CORK, NULL); } + + +/** + * Write a log message with a custom log level + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(3) inline int +liblog_vlog(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) +{ return liblog_xlog(ctx, level, 0, fmt, args); } + +/** + * Write a log message with a custom log level + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(3) inline int +liblog_log(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vlog, ctx, level, fmt); } + +/** + * Write a log message with a custom log level + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(3) inline int +liblog_vlog_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) +{ return liblog_xlog(ctx, level, LIBLOG_XLOG_CORK, fmt, args); } + +/** + * Write a log message with a custom log level + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(3) inline int +liblog_log_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vlog_cork, ctx, level, fmt); } + + +/** + * Write a log message with a custom log level + * + * Even if configured that backtraces should be printed for the + * the specificed log level, no backtrace will be printed + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(3) inline int +liblog_vlog_no_backtrace(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) +{ return liblog_xlog(ctx, level, LIBLOG_XLOG_NO_BACKTRACE, fmt, args); } + +/** + * Write a log message with a custom log level + * + * Even if configured that backtraces should be printed for the + * the specificed log level, no backtrace will be printed + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(3) inline int +liblog_log_no_backtrace(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vlog_no_backtrace, ctx, level, fmt); } + +/** + * Write a log message with a custom log level + * + * Even if configured that backtraces should be printed for the + * the specificed log level, no backtrace will be printed + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(3) inline int +liblog_vlog_no_backtrace_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) +{ return liblog_xlog(ctx, level, LIBLOG_XLOG_NO_BACKTRACE | LIBLOG_XLOG_CORK, fmt, args); } + +/** + * Write a log message with a custom log level + * + * Even if configured that backtraces should be printed for the + * the specificed log level, no backtrace will be printed + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param level The log level for the message; does not have to + * be predefined in `enum liblog_level` + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(3) inline int +liblog_log_no_backtrace_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vlog_no_backtrace_cork, ctx, level, fmt); } + + +/* Everything from this point onwards is just for convenience */ + + +/** + * Write a log message with log level `LIBLOG_EMERGENCY` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vemergency(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_EMERGENCY, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_EMERGENCY` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_emergency(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vemergency, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_EMERGENCY` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vemergency_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_EMERGENCY, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_EMERGENCY` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_emergency_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vemergency_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_ALERT` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_valert(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_ALERT, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_ALERT` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_alert(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_valert, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_ALERT` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_valert_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_ALERT, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_ALERT` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_alert_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_valert_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_CRITICAL` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vcritical(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_CRITICAL, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_CRITICAL` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_critical(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vcritical, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_CRITICAL` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vcritical_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_CRITICAL, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_CRITICAL` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_critical_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vcritical_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_ERROR` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_verror(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_ERROR, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_ERROR` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_error(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_verror, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_ERROR` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_verror_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_ERROR, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_ERROR` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_error_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_verror_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_WARNING` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vwarning(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_WARNING, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_WARNING` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_warning(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vwarning, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_WARNING` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vwarning_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_WARNING, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_WARNING` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_warning_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vwarning_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_NOTICE` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vnotice(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_NOTICE, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_NOTICE` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_notice(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vnotice, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_NOTICE` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vnotice_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_NOTICE, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_NOTICE` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_notice_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vnotice_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_INFO` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vinfo(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_INFO, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_INFO` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_info(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vinfo, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_INFO` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vinfo_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_INFO, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_INFO` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_info_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vinfo_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_TRACE` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vtrace(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_TRACE, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_TRACE` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_trace(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vtrace, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_TRACE` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vtrace_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_TRACE, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_TRACE` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_trace_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vtrace_cork, ctx, fmt); } + + +/** + * Write a log message with log level `LIBLOG_DEBUG` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vdebug(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog(ctx, LIBLOG_DEBUG, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_DEBUG` + * + * The log message is printed immediately as one complete log message + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_debug(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vdebug, ctx, fmt); } + +/** + * Write a log message with log level `LIBLOG_DEBUG` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param args Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_VPRINTF__(2) inline int +liblog_vdebug_cork(struct liblog_context *ctx, const char *fmt, va_list args) +{ return liblog_vlog_cork(ctx, LIBLOG_DEBUG, fmt, args); } + +/** + * Write a log message with log level `LIBLOG_DEBUG` + * + * The log message is treated as incomplete, and can be extended using + * any log message writing function using the same `ctx`, and will be + * printed once `liblog_uncork` is called using the same `ctx` + * + * @param ctx Logging configurations and state + * @param fmt printf(3) format string for the log message + * @param ... Arguments for `fmt` + * @return 0 on success, -1 on failure + */ +LIBLOG_PRINTF__(2) inline int +liblog_debug_cork(struct liblog_context *ctx, const char *fmt, ...) +{ LIBLOG_VA__(liblog_vdebug_cork, ctx, fmt); } + + + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + +#endif |
