#include #include #include #include #include "toolbox.hpp" namespace asp { static const constexpr size_t N_TIMES = 10; static const constexpr std::array time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y" }; static const constexpr std::array time_numbers = { 1, 1000, 1000, 1000, 60, 60, 24, 7, 4, 12 }; static const uint64_t total_time = std::accumulate(time_numbers.begin(), time_numbers.end(), (uint64_t)1, std::multiplies()); static const constexpr size_t N_BYTES = 7; static const constexpr std::array bytes_formats = { "", "K", "M", "G", "P", "E", "Z" }; //, "Y" }; static const constexpr uint64_t total_bytes = static_cast(1)<<(10 * (N_BYTES - 1)); /** * @brief Format the time in seconds in human readable format. * * @param time Time in seconds * @return std::string The formatted human readable string. */ std::string format_time(const uint64_t time) noexcept { return time < 2 ? std::to_string(time) + "s" : format_time_ns(time * (uint64_t)1e9); } /** * @brief Format the time in nanoseconds in human readable format. * * @param time Time in nanoseconds * @return std::string The formatted human readable string. */ std::string format_byte_size(uint64_t bytes) noexcept { if (bytes == 0) return "0B"; uint64_t prod = total_bytes; std::string s = ""; uint64_t res; for (size_t i = N_BYTES; i > 0; --i) { if (bytes >= prod) { res = bytes / prod; bytes %= prod; s += std::to_string(res) + bytes_formats[i - 1] + "B "; } prod /= static_cast(1)<<10; } if (s.back() == ' ') s.pop_back(); return s; } /** * @brief Format the time in nanoseconds in human readable format. * * @param time Time in nanoseconds * @return std::string The formatted human readable string. */ std::string format_time_ns(uint64_t time) noexcept { if (time == 0) return "0ns"; uint64_t prod = total_time; std::string s = ""; uint64_t res; for (size_t i = N_TIMES; i > 0; --i) { if (time >= prod) { res = time / prod; time %= prod; s += std::to_string(res) + time_formats[i - 1] + " "; } prod /= time_numbers[i - 1]; } if (s.back() == ' ') s.pop_back(); return s; } /** * @brief Run some unitary tests on format functions * */ void toolbox_unit_test() noexcept { assert(std::string("0B") == format_byte_size(static_cast(0))); assert(std::string("1B") == format_byte_size(static_cast(1))); assert(std::string("1KB") == format_byte_size(static_cast(1)<<10)); assert(std::string("1MB") == format_byte_size(static_cast(1)<<20)); assert(std::string("1GB") == format_byte_size(static_cast(1)<<30)); assert(std::string("1PB") == format_byte_size(static_cast(1)<<40)); assert(std::string("1EB") == format_byte_size(static_cast(1)<<50)); assert(std::string("1ZB") == format_byte_size(static_cast(1)<<60)); //assert(std::string("1YB") == format_byte_size(static_cast(1)<<70)); // UINT64_MAX == 18446744073709551615I64u == -1 assert(std::string("15ZB 1023EB 1023PB 1023GB 1023MB 1023KB 1023B") == format_byte_size(static_cast(-1))); assert(std::string("0s") == format_time(static_cast(0))); assert(std::string("1s") == format_time(static_cast(1))); assert(std::string("1m") == format_time(static_cast(60))); assert(std::string("1h") == format_time(static_cast(3600))); assert(std::string("1j") == format_time(static_cast(86400))); assert(std::string("1w") == format_time(static_cast(604800))); assert(std::string("1M") == format_time(static_cast(2419200))); assert(std::string("1y") == format_time(static_cast(29030400))); assert(std::string("0ns") == format_time_ns(static_cast(0))); assert(std::string("1ns") == format_time_ns(static_cast(1))); assert(std::string("1us") == format_time_ns(static_cast(1e3))); assert(std::string("1ms") == format_time_ns(static_cast(1e6))); assert(std::string("1s") == format_time_ns(static_cast(1e9))); assert(std::string("1m") == format_time_ns(static_cast(6e10))); assert(std::string("1h") == format_time_ns(static_cast(36e11))); assert(std::string("1j") == format_time_ns(static_cast(864e11))); assert(std::string("1w") == format_time_ns(static_cast(6048e11))); assert(std::string("1M") == format_time_ns(static_cast(24192e11))); assert(std::string("1y") == format_time_ns(static_cast(290304e11))); // UINT64_MAX == 18446744073709551615I64u == -1 assert(std::string("635y 5M 3j 23h 34m 33s 709ms 551us 615ns") == format_time_ns(static_cast(-1))); } std::string thousand_sep(const uint64_t& k, const char& sep) noexcept { std::string s = "", n = std::to_string(k); int c = 0; for (int i = static_cast(n.size()) - 1; i >= 0; --i) { c++; s.push_back(n[i]); if (c == 3) { s.push_back(sep); c = 0; } } std::reverse(s.begin(), s.end()); if (s.size() % 4 == 0) s.erase(s.begin()); return s; } std::string thousand_sep(const uint64_t& k) noexcept { return thousand_sep(k, ','); } void print_separator(const char* title) noexcept { #define S(N) std::string(N, '-').c_str() const constexpr size_t SEPARATOR_SIZE = W_NAME + W_TIME + W_FTIME + 6 + 6; char separator[SEPARATOR_SIZE]; sprintf(separator, "|%s|%s|%s|\n", S(W_NAME + 2), S(W_TIME + 2), S(W_FTIME + 2)); printf("| %-" STR(W_NAME) "s | %-" STR(W_TIME) "s | %-" STR(W_FTIME) "s | \n%s", title, "Time spent(ns)", "Formatted time spent", separator); } }