From d0493890f113c3d7ca683ad21c9a591e5a98d49f Mon Sep 17 00:00:00 2001 From: saundersp Date: Mon, 24 Jul 2023 02:22:57 +0200 Subject: [PATCH] cpp : fixed format_time, format_time_ns and thousand_sep --- cpp/toolbox.cpp | 115 ++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 67 deletions(-) diff --git a/cpp/toolbox.cpp b/cpp/toolbox.cpp index 6dbd963..ebdf470 100644 --- a/cpp/toolbox.cpp +++ b/cpp/toolbox.cpp @@ -1,13 +1,13 @@ #include "toolbox.hpp" #include -#include -#include #include -static constexpr size_t N_TIMES = 10; -static const std::array time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y" }; -static 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 constexpr uint64_t u64(const double& n) noexcept { return static_cast(n); } + +static const constexpr size_t N_TIMES = 11; +static const constexpr std::array time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y", "c" }; +static const constexpr std::array time_numbers = { 1, u64(1e3), u64(1e6), u64(1e9), u64(6e10), u64(36e11), u64(864e11), + u64(6048e11), u64(26784e11), u64(31536e12), u64(31536e14) }; /** * @brief Format the time in seconds in human readable format. @@ -16,7 +16,24 @@ static const uint64_t total_time = std::accumulate(time_numbers.begin(), time_nu * @return std::string The formatted human readable string. */ std::string format_time(uint64_t time) noexcept { - return time < 2 ? std::to_string(time) + "s" : format_time_ns(time * (uint64_t)1e9); + if (time == 0) + return "0s"; + + std::string s = ""; + uint64_t res; + for (int i = N_TIMES - 1; i >= 3; --i) { + const uint64_t time_number = time_numbers[i] / 1e9; // Converting nanosecond timestamp to second + if (time >= time_number) { + res = time / time_number; + time %= time_number; + s += std::to_string(res) + time_formats[i] + " "; + } + } + + if (s.back() == ' ') + s.pop_back(); + + return s; } /** @@ -28,17 +45,15 @@ std::string format_time(uint64_t time) noexcept { 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 (int i = N_TIMES - 1; i >= 0; --i) { - if (time >= prod) { - res = time / prod; - time %= prod; + if (time >= time_numbers[i]) { + res = time / time_numbers[i]; + time %= time_numbers[i]; s += std::to_string(res) + time_formats[i] + " "; } - prod /= time_numbers[i]; } if (s.back() == ' ') @@ -48,9 +63,16 @@ std::string format_time_ns(uint64_t time) noexcept { } 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)); +static const constexpr std::array bytes_formats = { "", "K", "M", "G", "T", "P", "E", }; //"Z", "Y" }; +static const constexpr uint64_t total_bytes = u64(1)<<(10 * (N_BYTES - 1)); +/** + * @brief Convert the number of byte in JEDEC standard form. + * See more : https://en.wikipedia.org/wiki/JEDEC_memory_standards + * + * @param bytes Number of bytes + * @return std::string JEDEC compliant formatted number of bytes + */ std::string format_byte_size(uint64_t bytes) noexcept { if (bytes == 0) return "0B"; @@ -64,70 +86,29 @@ std::string format_byte_size(uint64_t bytes) noexcept { bytes %= prod; s += std::to_string(res) + bytes_formats[i - 1] + "B "; } - prod /= static_cast(1)<<10; + prod /= u64(1)<<10; // 1024 } - if (s.back() == ' ') - s.pop_back(); + // Remove trailing character + s.pop_back(); return s; } -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))); +std::string thousand_sep(uint64_t k, const char& separator) noexcept { + const std::string n = std::to_string(k); + const uint64_t st_size = n.length() + (n.length() - 1) / 3; + std::string s = std::string(st_size, ' '); - 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(uint64_t k) noexcept { - std::string s = "", n = std::to_string(k); - - uint8_t c = 0; - for (const char& n_i : n) { - ++c; - s.push_back(n_i); - if (c == 3) { - s.push_back(','); + int8_t c = 0, n_i = n.length() - 1, j = st_size - 1; + for(; n_i >= 0; --n_i) { + s[j--] = n[n_i]; + if (++c == 3 && j >= 0) { + s[j--] = separator; c = 0; } } - std::reverse(s.begin(), s.end()); - - if (s.size() % 4 == 0) - s.erase(s.begin()); - return s; }