You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.6 KiB
110 lines
3.6 KiB
#pragma once
|
|
|
|
/**
|
|
* @file
|
|
* Implementation of custom assert and debug utilities.
|
|
*/
|
|
|
|
#include <tinyformat.h>
|
|
#include "print.hpp"
|
|
|
|
namespace meshless {
|
|
|
|
#ifdef _MSC_VER // Check if using MSVC
|
|
#define FUNCTION_NAME __FUNCSIG__ // Use __FUNCSIG__ for function name
|
|
#else
|
|
#define FUNCTION_NAME __PRETTY_FUNCTION__ // Use __PRETTY_FUNCTION__ for other compilers
|
|
#endif
|
|
|
|
|
|
// print macro
|
|
/// @cond
|
|
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
|
|
#define VA_NUM_ARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
|
|
#define macro_dispatcher(func, ...) macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__))
|
|
#define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs)
|
|
#define macro_dispatcher__(func, nargs) func ## nargs
|
|
#define addflag(a) {std::cerr << "flags=[flags, " << (a) << "];" << std::endl;}
|
|
#define prnv2(a, b) {std::cerr << a << " = " << (b) << ";" << std::endl;}
|
|
#define prnv1(a) {std::cerr << #a << " = " << (a) << ";" << std::endl;}
|
|
/// @endcond
|
|
/**
|
|
* Prints a variable name and value to standard output. Can take one or two parameters.
|
|
* Example:
|
|
* @code
|
|
* int a = 6;
|
|
* prn(a) // prints 'a = 6;'
|
|
* prn("value", a) // prints 'value = 6;'
|
|
* @endcode
|
|
*/
|
|
#define prn(...) macro_dispatcher(prnv, __VA_ARGS__)(__VA_ARGS__)
|
|
|
|
using tinyformat::printf;
|
|
using tinyformat::format;
|
|
|
|
/// Namespace holding custom assert implementation.
|
|
namespace assert_internal {
|
|
/**
|
|
* Actual assert implementation.
|
|
* @param condition Condition to test, e.g.\ `n > 0`.
|
|
* @param file File where the assertion failed.
|
|
* @param func_name Function name where the assertion failed.
|
|
* @param line Line on which the assertion failed.
|
|
* @param message Message as specified in the `assert_msg` macro.
|
|
* @param format_list List of format field values to pass to `tinyformat::format` function.
|
|
*/
|
|
bool assert_handler_implementation(const char* condition, const char* file, const char* func_name,
|
|
int line, const char* message, tfm::FormatListRef format_list);
|
|
/// Assert handler that unpacks varargs.
|
|
template<typename... Args>
|
|
bool assert_handler(const char* condition, const char* file, const char* func_name, int line,
|
|
const char* message, const Args&... args) { // unpacks first argument
|
|
tfm::FormatListRef arg_list = tfm::makeFormatList(args...);
|
|
return assert_handler_implementation(condition, file, func_name, line, message, arg_list);
|
|
}
|
|
} // namespace assert_internal
|
|
|
|
#ifdef NDEBUG
|
|
#define assert_msg(cond, ...) ((void)sizeof(cond))
|
|
#else
|
|
/**
|
|
* @brief Assert with better error reporting.
|
|
* @param cond Conditions to test.
|
|
* @param ... The second parameter is also required and represents the message to print on failure.
|
|
* For every %* field in message one additional parameter must be present.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* assert_msg(n > 0, "n must be positive, got %d.", n);
|
|
* @endcode
|
|
*/
|
|
#define assert_msg(cond, ...) ((void)(!(cond) && \
|
|
meshless::assert_internal::assert_handler( \
|
|
#cond, __FILE__, FUNCTION_NAME, __LINE__, __VA_ARGS__) && (assert(0), 1)))
|
|
// #cond, __FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__) && (exit(1), 1)))
|
|
#endif
|
|
|
|
/**
|
|
* Prints given text in bold red.
|
|
* @param s text to print.
|
|
*/
|
|
inline void print_red(const std::string& s) {
|
|
std::cout << "\x1b[31;1m" << s << "\x1b[37;0m";
|
|
}
|
|
/**
|
|
* Prints given text in bold white.
|
|
* @param s text to print.
|
|
*/
|
|
inline void print_white(const std::string& s) {
|
|
std::cout << "\x1b[37;1m" << s << "\x1b[37;0m";
|
|
}
|
|
/**
|
|
* Prints given text in bold green.
|
|
* @param s text to print.
|
|
*/
|
|
inline void print_green(const std::string& s) {
|
|
std::cout << "\x1b[32;1m" << s << "\x1b[37;0m";
|
|
}
|
|
|
|
} // namespace meshless
|
|
|
|
|