toolbox/format_bytes/src/format_bytes.cpp

67 lines
1.7 KiB
C++

#include <string>
#include <array>
#include <stdint.h>
#include "toolbox.hpp"
static constexpr const size_t STRING_BUFFER_SIZE = 64;
static constexpr const std::array<const char[3], 7> format_prefix = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
/**
* @brief Convert a given numbers of bytes to a human readable format
*
* @param n Number of bytes
* @return Human readable format of the numbers of bytes
*/
std::string format_bytes(uint64_t n) noexcept {
char s[STRING_BUFFER_SIZE] = { 0 };
if(n == 0){
sprintf(s, "0%s", format_prefix[0]);
return s;
}
size_t j = 0;
for(int8_t i = static_cast<int8_t>(format_prefix.size() - 1) * 10; i >= 0; i -= 10){
const uint64_t nsi = n >> i;
if(nsi > 0){
const int8_t idx = i / 10;
j += ullstr(nsi, j, s);
for(int k = 0; format_prefix[idx][k] > 0; ++k)
s[j++] = format_prefix[idx][k];
s[j++] = ' ';
n &= u64(-1) >> (64 - i);
}
}
/* Remove trailing character */
s[j - 1] = '\0';
return std::string(s);
}
#ifndef TEST
int32_t main(const int32_t argc, const char* const* argv) noexcept {
uint64_t n = 0;
if (argc > 2) return fprintf(stderr, "Invalid usage : (%s $NUMBER) or (echo $NUMBER | %s)\n", argv[0], argv[0]);
else if (argc == 2){
if(sstrtoull(argv[1], n) == EXIT_FAILURE)
return EXIT_FAILURE;
} else {
size_t i = 0;
char BUFFER[STRING_BUFFER_SIZE];
for(int c; i < STRING_BUFFER_SIZE && (c = fgetc(stdin)) != EOF; ++i)
BUFFER[i] = c;
if(i == STRING_BUFFER_SIZE){
fprintf(stderr, "Error while converting to integer : invalid stdin input (too large)\n");
return EXIT_FAILURE;
}
if(sstrtoull(BUFFER, n) == EXIT_FAILURE)
return EXIT_FAILURE;
}
printf("%s\n", format_bytes(n).c_str());
return EXIT_SUCCESS;
}
#endif