cube

A rotating 3D wireframe cube rendered in the terminal
git clone https://github.com/michaelneuper/cube.git
README | Files | Log | Refs | LICENSE

cube/src/debug.h (6636B)


/**
 * @file    debug.h
 * @author  Michael Neuper (michael@michaelneuper.com)
 *
 * Debug utilities: assertion macros that print the failing
 * expression with operand values and abort. All macros are no-ops
 * unless compiled with -DDEBUG.
 */

#ifndef DEBUG_H_
#define DEBUG_H_

#include <stdio.h>
#include <stdlib.h>

#define FORMAT_SPECIFIER(x)                                                    \
    _Generic((x),                                                              \
        char: "%c",                                                            \
        signed char: "%hhd",                                                   \
        unsigned char: "%hhu",                                                 \
        short: "%hd",                                                          \
        unsigned short: "%hu",                                                 \
        int: "%d",                                                             \
        unsigned int: "%u",                                                    \
        long: "%ld",                                                           \
        unsigned long: "%lu",                                                  \
        long long: "%lld",                                                     \
        unsigned long long: "%llu",                                            \
        float: "%f",                                                           \
        double: "%f",                                                          \
        long double: "%Lf",                                                    \
        char *: "%s",                                                          \
        const char *: "%s",                                                    \
        void *: "%p",                                                          \
        default: "unknown type (0x%p)")

#ifdef DEBUG
#    define ASSERT(cond, fmt, ...)                                             \
        do {                                                                   \
            if (!(cond)) {                                                     \
                fprintf(stderr,                                                \
                        "\e[1m%s:%d: \e[31massertion failed:\e[m\n '%s'.",     \
                        __FILE__, __LINE__, #cond);                            \
                fprintf(stderr, fmt, ##__VA_ARGS__);                           \
                abort();                                                       \
            }                                                                  \
        } while (0)
#else
#    define ASSERT(cond, fmt, ...) ((void)0)
#endif

#define ASSERT_EQ(a, b)                                                        \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        const char *fb__ = FORMAT_SPECIFIER(b);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s, %%s = %s\n", fa__, fb__);     \
        ASSERT((a) == (b), fmt__, #a, (a), #b, (b));                           \
    } while (0)

#define ASSERT_NE(a, b)                                                        \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        const char *fb__ = FORMAT_SPECIFIER(b);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s, %%s = %s\n", fa__, fb__);     \
        ASSERT((a) != (b), fmt__, #a, (a), #b, (b));                           \
    } while (0)

#define ASSERT_LT(a, b)                                                        \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        const char *fb__ = FORMAT_SPECIFIER(b);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s, %%s = %s\n", fa__, fb__);     \
        ASSERT((a) < (b), fmt__, #a, (a), #b, (b));                            \
    } while (0)

#define ASSERT_LE(a, b)                                                        \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        const char *fb__ = FORMAT_SPECIFIER(b);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s, %%s = %s\n", fa__, fb__);     \
        ASSERT((a) <= (b), fmt__, #a, (a), #b, (b));                           \
    } while (0)

#define ASSERT_NZ(a)                                                           \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s\n", fa__);                     \
        ASSERT((a) != 0, fmt__, #a, (a));                                      \
    } while (0)

#define ASSERT_GZ(a)                                                           \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s\n", fa__);                     \
        ASSERT((a) > 0, fmt__, #a, (a));                                       \
    } while (0)

#define ASSERT_GEZ(a)                                                          \
    do {                                                                       \
        const char *fa__ = FORMAT_SPECIFIER(a);                                \
        char        fmt__[64];                                                 \
        snprintf(fmt__, sizeof fmt__, "%%s = %s\n", fa__);                     \
        ASSERT((a) >= 0, fmt__, #a, (a));                                      \
    } while (0)

#define ASSERT_NOT_NULL(a) ASSERT_NE((a), NULL)

#endif // DEBUG_H_