RPNX::QueryGraph
Typed, memoized, concurrent query evaluation for C++23
Loading...
Searching...
No Matches
byte_format.hpp
Go to the documentation of this file.
1#ifndef RPNXQUERYGRAPH_BYTE_FORMAT_HPP
2#define RPNXQUERYGRAPH_BYTE_FORMAT_HPP
3
8
9#include <algorithm>
10#include <cmath>
11#include <cstddef>
12#include <iomanip>
13#include <sstream>
14#include <string>
15
16namespace rpnx::querygraph
17{
28 inline std::string format_iec_bytes(std::size_t bytes)
29 {
30 static constexpr const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
31 static constexpr std::size_t unit_count = sizeof(units) / sizeof(units[0]);
32
33 if (bytes == 0)
34 {
35 return "0B";
36 }
37
38 double value = static_cast< double >(bytes);
39 std::size_t unit_index = 0;
40 while (value >= 1024.0 && unit_index + 1 < unit_count)
41 {
42 value /= 1024.0;
43 ++unit_index;
44 }
45
46 auto decimals_for = [](double v) -> std::ptrdiff_t
47 {
48 if (v <= 0.0)
49 {
50 return 0;
51 }
52 auto const digits = static_cast< std::ptrdiff_t >(std::floor(std::log10(v))) + 1;
53 return std::max< std::ptrdiff_t >(0, 3 - digits);
54 };
55
56 auto decimals = decimals_for(value);
57 double scale = std::pow(10.0, static_cast< double >(decimals));
58 double rounded = std::round(value * scale) / scale;
59
60 if (rounded >= 1024.0 && unit_index + 1 < unit_count)
61 {
62 value = rounded / 1024.0;
63 ++unit_index;
64 decimals = decimals_for(value);
65 scale = std::pow(10.0, static_cast< double >(decimals));
66 rounded = std::round(value * scale) / scale;
67 }
68
69 std::ostringstream oss;
70 if (unit_index == 0)
71 {
72 oss << bytes << units[unit_index];
73 return oss.str();
74 }
75
76 oss << std::fixed << std::setprecision(static_cast< int >(decimals)) << rounded << units[unit_index];
77 return oss.str();
78 }
79} // namespace rpnx::querygraph
80
81#endif // RPNXQUERYGRAPH_BYTE_FORMAT_HPP
std::string format_iec_bytes(std::size_t bytes)
Format a byte count using IEC binary units.