Skip to content

Commit

Permalink
Add right fold, and a way to disable logging
Browse files Browse the repository at this point in the history
  • Loading branch information
agagniere committed Sep 3, 2024
1 parent 34e5a8d commit 08e3268
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 31 deletions.
5 changes: 5 additions & 0 deletions include/blackmagic/blackmagic.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@
* This directory contains all blackmagic headers.
* Do not add it directly to the search path for headers, prefer instead the `include` directory
*/

/**
* @mainpage
* Welcome to the documentation of black magic.
*/
5 changes: 3 additions & 2 deletions include/blackmagic/color.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "blackmagic/token.h" // STRINGIZE
#include "blackmagic/fold.h" // FOLD

#define NORMAL 0
#define BOLD 1
Expand Down Expand Up @@ -31,5 +32,5 @@
#define BG_DEFAULT 49
#define BG_WHITE 107

#define _COLOR_JOIN(A, B) A;B
#define COLOR(...) STRINGIZE(\e[FOLD_RIGHT(_COLOR_JOIN, __VA_ARGS__)m)
#define COLOR_JOIN(A, B) A;B
#define COLOR(...) STRINGIZE(\e[FOLD(COLOR_JOIN __VA_OPT__(,) __VA_ARGS__)m)
44 changes: 44 additions & 0 deletions include/blackmagic/fold.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
#include "blackmagic/arg_count.h" // ARG_COUNT
#include "blackmagic/token.h" // CONCAT

/** @name Configuration */
///@{
#ifndef FOLD
/** Default fold to use, can be overridden */
# define FOLD TREE_FOLD
#endif
///@}

/**
* Apply the binary macro @p M on pairs of inputs, in a tree-like fashion.
* __Example__
Expand All @@ -23,6 +31,20 @@
*/
#define TREE_FOLD(M, ...) CONCAT(TREE_FOLD_, ARG_COUNT(__VA_ARGS__))(M __VA_OPT__(,) __VA_ARGS__)

/**
* Apply the binary macro @p M on pairs of inputs, first grouping the right-most arguments.
* __Example__
* @code{.c}
* FOLD_RIGHT(F, A, B, C, D)
* @endcode
* expands to:
* @code{.c}
* F(A, F(B, F(C, D)))
* @endcode
* @since 0.2
*/
#define FOLD_RIGHT(M, ...) CONCAT(FOLD_RIGHT_, ARG_COUNT(__VA_ARGS__))(M __VA_OPT__(,) __VA_ARGS__)

#define TREE_FOLD_0(M)
#define TREE_FOLD_1(M, A) A
#define TREE_FOLD_2(M, A, B) M(A, B)
Expand All @@ -44,3 +66,25 @@
#define TREE_FOLD_18(M, A, B, ...) M(M(A, B), TREE_FOLD_16(M, __VA_ARGS__))
#define TREE_FOLD_19(M, A, B, C, ...) M(M(A, M(B, C)), TREE_FOLD_16(M, __VA_ARGS__))
#define TREE_FOLD_20(M, A, B, C, D, ...) M(M(M(A, B), M(C, D)), TREE_FOLD_16(M, __VA_ARGS__))

#define FOLD_RIGHT_0(M)
#define FOLD_RIGHT_1(M, A) A
#define FOLD_RIGHT_2(M, A, B) M(A, B)
#define FOLD_RIGHT_3(M, A, B, C) M(A, M(B, C))
#define FOLD_RIGHT_4(M, A, B, C, D) M(A, M(B, M(C, D)))
#define FOLD_RIGHT_5(M, A, B, C, D, E) M(A, M(B, M(C, M(D, E))))
#define FOLD_RIGHT_6(M, A, ...) M(A, FOLD_RIGHT_5(M, __VA_ARGS__))
#define FOLD_RIGHT_7(M, A, B, ...) M(A, M(B, FOLD_RIGHT_5(M, __VA_ARGS__)))
#define FOLD_RIGHT_8(M, A, B, C, ...) M(A, M(B, M(C, FOLD_RIGHT_5(M, __VA_ARGS__))))
#define FOLD_RIGHT_9(M, A, ...) M(A, FOLD_RIGHT_8(M, __VA_ARGS__))
#define FOLD_RIGHT_10(M, A, ...) M(A, FOLD_RIGHT_9(M, __VA_ARGS__))
#define FOLD_RIGHT_11(M, A, ...) M(A, FOLD_RIGHT_10(M, __VA_ARGS__))
#define FOLD_RIGHT_12(M, A, ...) M(A, FOLD_RIGHT_11(M, __VA_ARGS__))
#define FOLD_RIGHT_13(M, A, ...) M(A, FOLD_RIGHT_12(M, __VA_ARGS__))
#define FOLD_RIGHT_14(M, A, ...) M(A, FOLD_RIGHT_13(M, __VA_ARGS__))
#define FOLD_RIGHT_15(M, A, ...) M(A, FOLD_RIGHT_14(M, __VA_ARGS__))
#define FOLD_RIGHT_16(M, A, ...) M(A, FOLD_RIGHT_15(M, __VA_ARGS__))
#define FOLD_RIGHT_17(M, A, ...) M(A, FOLD_RIGHT_16(M, __VA_ARGS__))
#define FOLD_RIGHT_18(M, A, ...) M(A, FOLD_RIGHT_17(M, __VA_ARGS__))
#define FOLD_RIGHT_19(M, A, ...) M(A, FOLD_RIGHT_18(M, __VA_ARGS__))
#define FOLD_RIGHT_20(M, A, ...) M(A, FOLD_RIGHT_19(M, __VA_ARGS__))
58 changes: 29 additions & 29 deletions include/blackmagic/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

/**
* @name Configuration
* These settings can be overridden using the compiler's `-D` flag
* These settings can be overridden using the compiler's `-D` flag or using a `#define` before `#include`
*/
///@{

Expand All @@ -33,7 +33,7 @@
/**
* Choose the compile-time log verbosity level.
* Logs that are strictly less critical that this level are removed before compilation.
* The default value is TRACE for debug builds and INFO for release builds that define `NDEBUG`.
* The default value is @ref LOG_LEVEL_TRACE for debug builds and @ref LOG_LEVEL_INFO for release builds that define `NDEBUG`.
*/
# define LOG_LEVEL LOG_LEVEL_TRACE
# endif
Expand All @@ -51,7 +51,7 @@
* Possible values of @ref LOG_LEVEL
*/
///@{
#define LOG_LEVEL_NONE 0 /**< Set @ref LOG_LEVEL to this value to disable logs */
#define LOG_LEVEL_NONE 0 /**< Only output the header and forced logs */
#define LOG_LEVEL_FATAL 1 /**< The program will stop */
#define LOG_LEVEL_ERROR 3 /**< The current operation will abort */
#define LOG_LEVEL_WARNING 4 /**< Abnormal situation */
Expand All @@ -65,6 +65,8 @@
* Possible values of @ref LOG_FORMAT
*/
///@{
/** Disable outputting logs */
#define LOG_FORMAT_NONE 0
/** Print logs in a human readable format without colors */
#define LOG_FORMAT_CONSOLE 1
/** Print logs in a human readable format with colors */
Expand All @@ -76,66 +78,64 @@
#if LOG_FORMAT == LOG_FORMAT_MARKDOWN
# define log_header() fprintf(LOG_FILE, "|Level|File|Function|Line|Message|\n|:-|:-|:-|-:|:-|\n")
#else
# define log_header() /**< Place this macro before any log */
# define log_header() /**< Place this macro once before any log */
#endif

#if LOG_FORMAT == LOG_FORMAT_CONSOLE
# define log_log(LEVEL, IGNORED, MESSAGE, ...) \
fprintf(LOG_FILE, "[%5s " __FILE__ ":%s:" STRINGIZE(__LINE__) "] " MESSAGE "\n", \
LEVEL, __func__ __VA_OPT__(,) __VA_ARGS__)
fprintf(LOG_FILE, "[%5s " __FILE__ ":%s:" STRINGIZE(__LINE__) "] " MESSAGE "\n", LEVEL, __func__ __VA_OPT__(, ) __VA_ARGS__)
#elif LOG_FORMAT == LOG_FORMAT_COLOR
# define log_log(LEVEL, COLOR_STRING, MESSAGE, ...) \
fprintf(LOG_FILE, "[" COLOR_STRING "%5s" COLOR(DIM, DEFAULT, BG_DEFAULT) " " __FILE__ ":%s:" STRINGIZE(__LINE__) COLOR(NORMAL) "] " MESSAGE "\n", \
LEVEL, __func__ __VA_OPT__(,) __VA_ARGS__)
fprintf(LOG_FILE, \
"[" COLOR_STRING "%5s" COLOR(NORMAL) COLOR(DIM) " " __FILE__ ":%s:" STRINGIZE(__LINE__) COLOR(NORMAL) "] " MESSAGE "\n", LEVEL, __func__ __VA_OPT__(, ) __VA_ARGS__)
#elif LOG_FORMAT == LOG_FORMAT_MARKDOWN
# define log_log(LEVEL, IGNORED, MESSAGE, ...) \
fprintf(LOG_FILE, "|" LEVEL "|`" __FILE__ "`|`%s`|" STRINGIZE(__LINE__) "|" MESSAGE "|\n", \
__func__ __VA_OPT__(,) __VA_ARGS__)
fprintf(LOG_FILE, "|" LEVEL "|`" __FILE__ "`|`%s`|" STRINGIZE(__LINE__) "|" MESSAGE "|\n", __func__ __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_log(L, C, M, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_FATAL
/** Report a condition that forces to program to terminate */
# define log_fatal(MESSAGE, ...) \
log_log("FATAL", COLOR(BOLD, WHITE, BG_RED), MESSAGE __VA_OPT__(,) __VA_ARGS__)
# define log_fatal(MESSAGE, ...) log_log("FATAL", COLOR(BOLD, WHITE, BG_RED), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_fatal(M, ...)
# define log_fatal(M, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_ERROR
/** Report a condition that forces the current operation to be aborted */
# define log_error(MESSAGE, ...) \
log_log("ERROR", COLOR(BOLD, RED), MESSAGE __VA_OPT__(,) __VA_ARGS__)
# define log_error(MESSAGE, ...) log_log("ERROR", COLOR(BOLD, RED), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_error(M, ...)
# define log_error(M, ...)
#endif


#if LOG_LEVEL >= LOG_LEVEL_WARNING
/** Report an abnormal condition */
# define log_warning(MESSAGE, ...) \
log_log("WARN", COLOR(BOLD, YELLOW), MESSAGE __VA_OPT__(,) __VA_ARGS__)
# define log_warning(MESSAGE, ...) log_log("WARN", COLOR(BOLD, YELLOW), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_warning(M, ...)
# define log_warning(M, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_INFO
/** Report significant information */
# define log_info(MESSAGE, ...) \
log_log("INFO", COLOR(BOLD, GREEN), MESSAGE __VA_OPT__(,) __VA_ARGS__)
# define log_info(MESSAGE, ...) log_log("INFO", COLOR(BOLD, GREEN), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_info(M, ...)
# define log_info(M, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_DEBUG
# define log_debug(MESSAGE, ...) \
log_log("DEBUG", COLOR(BOLD, BLUE), MESSAGE __VA_OPT__(,) __VA_ARGS__)
/** Report information relevant to the developpers */
# define log_debug(MESSAGE, ...) log_log("DEBUG", COLOR(BOLD, BLUE), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_debug(M, ...)
# define log_debug(M, ...)
#endif

#if LOG_LEVEL >= LOG_LEVEL_TRACE
# define log_trace(MESSAGE, ...) \
log_log("TRACE", COLOR(NORMAL), MESSAGE __VA_OPT__(,) __VA_ARGS__)
/** Spam */
# define log_trace(MESSAGE, ...) log_log("TRACE", COLOR(NORMAL), MESSAGE __VA_OPT__(, ) __VA_ARGS__)
#else
# define log_trace(M, ...)
# define log_trace(M, ...)
#endif

/** Log regardless of level */
#define log_force(MESSAGE, ...) log_log("FORCE", COLOR(BOLD, WHITE, BG_GREEN), MESSAGE __VA_OPT__(, ) __VA_ARGS__)

0 comments on commit 08e3268

Please sign in to comment.