#pragma once #include #include #include #define W_NAME 49 #define W_TIME 17 #define W_FTIME 29 // Trick to insert preprocessor into strings #define STR_(X) #X #define STR(X) STR_(X) #define duration_ns(a) std::chrono::duration_cast(a).count() #define time() std::chrono::high_resolution_clock::now() namespace asp { std::string format_byte_size(uint64_t) noexcept; std::string format_time(const uint64_t) noexcept; std::string format_time_ns(uint64_t) noexcept; void toolbox_unit_test(void) noexcept; std::string thousand_sep(const uint64_t&, const char&) noexcept; std::string thousand_sep(const uint64_t&) noexcept; /** * @brief Print a formatted row of titles with of gaps seperated by a separator. * * @param gaps List of size gaps * @param titles List of titles * @param separator Separator character between each gap */ template constexpr void formatted_row(const std::array& gaps, const std::array& titles, const char* const separator = "│", const char line_ending = '\n') noexcept { for(size_t i = 0; i < N; ++i) printf("%s %*s ", separator, -gaps[i], titles[i]); printf("%s%c", separator, line_ending); } /** * @brief Print a formatted line of repeated characters. * * @param gaps List of size gaps * @param right Character on the left * @param middle Character between each separator * @param separator Separator character between each gap * @param left Character on the right */ template constexpr void formatted_line(const std::array& gaps, const char* const left, const char* const middle, const char* const separator, const char* const right, const char line_ending = '\n') noexcept { printf("%s", left); for(size_t i = 0; i < N; ++i){ for(int32_t j = std::abs(gaps[i]) + 2; j > 0; --j) printf("%s", separator); if(i != N - 1) printf("%s", middle); } printf("%s%c", right, line_ending); } /** * @brief Print a formatted header with the given titles and sizes. * * @param gaps List of size gaps * @param titles List of titles */ template constexpr void header(const std::array& gaps, const std::array& titles) noexcept { formatted_line(gaps, "┌", "┬", "─", "┐"); formatted_row(gaps, titles); formatted_line(gaps, "├", "┼", "─", "┤"); } /** * @brief Print a formatted footer with the given sizes. * * @param gaps List of size gaps */ template constexpr void footer(const std::array& gaps) noexcept { formatted_line(gaps, "└", "┴", "─", "┘"); } template constexpr void measure_time_void(const std::array& gaps, const char* step_name, const F& fnc, Args &&...args) noexcept { #ifndef __DEBUG formatted_row(gaps, { "Testing summary", "In progress", "In progress" }, "│", '\r'); #endif const auto start = time(); fnc(std::forward(args)...); const long long timespent = duration_ns(time() - start); formatted_row(gaps, { step_name, thousand_sep(timespent).c_str(), format_time_ns(timespent).c_str() }); } template constexpr T measure_time(const std::array& gaps, const char* step_name, const F& fnc, Args &&...args) noexcept { #ifndef __DEBUG formatted_row(gaps, { "Testing summary", "In progress", "In progress" }, "│", '\r'); #endif const auto start = time(); const T res = fnc(std::forward(args)...); const long long timespent = duration_ns(time() - start); formatted_row(gaps, { step_name, thousand_sep(timespent).c_str(), format_time_ns(timespent).c_str() }); return res; } };