/** This file is a part of rexy's general purpose library Copyright (C) 2022 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_DEBUG_PRINT_HPP #define REXY_DEBUG_PRINT_HPP #ifndef REXY_ENABLE_DEBUG_LEVEL #define REXY_ENABLE_DEBUG_LEVEL 0 #endif #ifndef REXY_ENABLE_COLOR_DEBUG #define REXY_ENABLE_COLOR_DEBUG 1 #endif //Debug output section #if REXY_ENABLE_DEBUG_LEVEL > 0 #define REXY_ENABLE_DEBUG_OUTPUT #endif #if REXY_ENABLE_DEBUG_LEVEL > 2 #define REXY_ENABLE_DEBUG_VERBOSE_OUTPUT #endif #ifdef REXY_ENABLE_DEBUG_OUTPUT #include //fprintf, vfprintf #include //forward #include "source_location.hpp" namespace rexy::debug{ namespace detail{ static constexpr const char color_red[] = "\033[38;5;9m"; static constexpr const char color_yellow[] = "\033[38;5;11m"; static constexpr const char color_green[] = "\033[38;5;2m"; static constexpr const char color_blue[] = "\033[38;5;12m"; static constexpr const char color_clear[] = "\033[0m"; } template struct print{ explicit print(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){ std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line()); std::fprintf(stderr, std::forward(args)...); } print(const print&) = delete; print(print&&) = delete; print& operator=(const print&) = delete; print& operator=(print&&) = delete; }; template print(Args&&...) -> print; #ifdef REXY_ENABLE_COLOR_DEBUG template struct print_succ{ explicit print_succ(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){ std::fprintf(stderr, "%s", detail::color_green); std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line()); std::fprintf(stderr, std::forward(args)...); std::fprintf(stderr, "%s", detail::color_clear); } print_succ(const print_succ&) = delete; print_succ(print_succ&&) = delete; print_succ& operator=(const print_succ&) = delete; print_succ& operator=(print_succ&&) = delete; }; template print_succ(Args&&...) -> print_succ; template struct print_info{ explicit print_info(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){ std::fprintf(stderr, "%s", detail::color_blue); std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line()); std::fprintf(stderr, std::forward(args)...); std::fprintf(stderr, "%s", detail::color_clear); } print_info(const print_info&) = delete; print_info(print_info&&) = delete; print_info& operator=(const print_info&) = delete; print_info& operator=(print_info&&) = delete; }; template print_info(Args&&...) -> print_info; template struct print_warn{ explicit print_warn(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){ std::fprintf(stderr, "%s", detail::color_yellow); std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line()); std::fprintf(stderr, std::forward(args)...); std::fprintf(stderr, "%s", detail::color_clear); } print_warn(const print_warn&) = delete; print_warn(print_warn&&) = delete; print_warn& operator=(const print_warn&) = delete; print_warn& operator=(print_warn&&) = delete; }; template print_warn(Args&&...) -> print_warn; template struct print_error{ explicit print_error(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){ std::fprintf(stderr, "%s", detail::color_red); std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line()); std::fprintf(stderr, std::forward(args)...); std::fprintf(stderr, "%s", detail::color_clear); } print_error(const print_error&) = delete; print_error(print_error&&) = delete; print_error& operator=(const print_error&) = delete; print_error& operator=(print_error&&) = delete; }; template print_error(Args&&...) -> print_error; #else template using print_succ = print; template using print_info = print; template using print_warn = print; template using print_error = print; #endif //REXY_ENABLE_COLOR_DEBUG #ifdef REXY_ENABLE_DEBUG_VERBOSE_OUTPUT namespace verbose{ template using print = rexy::debug::print; template using print_succ = rexy::debug::print_succ; template using print_info = rexy::debug::print_info; template using print_warn = rexy::debug::print_warn; template using print_error = rexy::debug::print_error; } #else namespace verbose{ static constexpr inline void print(...){} static constexpr inline void print_succ(...){} static constexpr inline void print_info(...){} static constexpr inline void print_warn(...){} static constexpr inline void print_error(...){} } #endif //REXY_ENABLE_DEBUG_VERBOSE_OUTPUT } #else static constexpr inline void print(...){} static constexpr inline void print_succ(...){} static constexpr inline void print_info(...){} static constexpr inline void print_warn(...){} static constexpr inline void print_error(...){} namespace verbose{ static constexpr inline void print(...){} static constexpr inline void print_succ(...){} static constexpr inline void print_info(...){} static constexpr inline void print_warn(...){} static constexpr inline void print_error(...){} } #endif //REXY_ENABLE_DEBUG_OUTPUT #endif