158 lines
5.3 KiB
C++
158 lines
5.3 KiB
C++
#include <numeric>
|
|
#include <cassert>
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include "toolbox.hpp"
|
|
|
|
namespace asp {
|
|
static constexpr size_t N_TIMES = 10;
|
|
static constexpr std::array<const char* const, N_TIMES> time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y" };
|
|
static constexpr std::array<uint16_t, N_TIMES> 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<uint64_t>());
|
|
|
|
static constexpr size_t N_BYTES = 7;
|
|
static constexpr std::array<const char*, N_BYTES> bytes_formats = { "", "K", "M", "G", "P", "E", "Z" }; //, "Y" };
|
|
static constexpr uint64_t total_bytes = uint64_t(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 /= uint64_t(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(void) noexcept {
|
|
assert(std::string("0B") == format_byte_size(uint64_t(0)));
|
|
assert(std::string("1B") == format_byte_size(uint64_t(1)));
|
|
assert(std::string("1KB") == format_byte_size(uint64_t(1)<<10));
|
|
assert(std::string("1MB") == format_byte_size(uint64_t(1)<<20));
|
|
assert(std::string("1GB") == format_byte_size(uint64_t(1)<<30));
|
|
assert(std::string("1PB") == format_byte_size(uint64_t(1)<<40));
|
|
assert(std::string("1EB") == format_byte_size(uint64_t(1)<<50));
|
|
assert(std::string("1ZB") == format_byte_size(uint64_t(1)<<60));
|
|
//assert(std::string("1YB") == format_byte_size(uint64_t(1)<<70));
|
|
// UINT64_MAX == 18446744073709551615I64u == -1
|
|
assert(std::string("15ZB 1023EB 1023PB 1023GB 1023MB 1023KB 1023B") == format_byte_size(uint64_t(-1)));
|
|
|
|
assert(std::string("0s") == format_time(uint64_t(0)));
|
|
assert(std::string("1s") == format_time(uint64_t(1)));
|
|
assert(std::string("1m") == format_time(uint64_t(60)));
|
|
assert(std::string("1h") == format_time(uint64_t(3600)));
|
|
assert(std::string("1j") == format_time(uint64_t(86400)));
|
|
assert(std::string("1w") == format_time(uint64_t(604800)));
|
|
assert(std::string("1M") == format_time(uint64_t(2419200)));
|
|
assert(std::string("1y") == format_time(uint64_t(29030400)));
|
|
|
|
assert(std::string("0ns") == format_time_ns(uint64_t(0)));
|
|
assert(std::string("1ns") == format_time_ns(uint64_t(1)));
|
|
assert(std::string("1us") == format_time_ns(uint64_t(1e3)));
|
|
assert(std::string("1ms") == format_time_ns(uint64_t(1e6)));
|
|
assert(std::string("1s") == format_time_ns(uint64_t(1e9)));
|
|
assert(std::string("1m") == format_time_ns(uint64_t(6e10)));
|
|
assert(std::string("1h") == format_time_ns(uint64_t(36e11)));
|
|
assert(std::string("1j") == format_time_ns(uint64_t(864e11)));
|
|
assert(std::string("1w") == format_time_ns(uint64_t(6048e11)));
|
|
assert(std::string("1M") == format_time_ns(uint64_t(24192e11)));
|
|
assert(std::string("1y") == format_time_ns(uint64_t(290304e11)));
|
|
// UINT64_MAX == 18446744073709551615I64u == -1
|
|
assert(std::string("635y 5M 3j 23h 34m 33s 709ms 551us 615ns") == format_time_ns(uint64_t(-1)));
|
|
}
|
|
|
|
std::string thousand_sep(const uint64_t& k, const char& sep) noexcept {
|
|
std::string s = "", n = std::to_string(k);
|
|
|
|
uint8_t c = 0;
|
|
for (int64_t i = int64_t(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* const title) noexcept {
|
|
#define S(N) std::string(N, '-').c_str()
|
|
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);
|
|
#undef S
|
|
}
|
|
}
|