/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include #include #include #include namespace openVulkanoCpp { class ByteSize final { static inline const std::regex REGEX_PATTERN = std::regex("\\s*(\\d+(\\.\\d*)?|\\.\\d+)\\s*([kMGTPE]i?)[Bb]\\s*"); size_t bytes; public: constexpr ByteSize(size_t size = 0) : bytes(size) {} ByteSize(const std::string& str) { std::smatch match; if (!std::regex_match(str, match, REGEX_PATTERN)) throw std::runtime_error("Unable to parse '" + str + "' as size."); double d=std::stod(match[1].str()); size_t mult = 1; if(match[3] == "ki") mult = 1LL<<10; else if(match[3] == "Mi") mult = 1LL<<20; else if(match[3] == "Gi") mult = 1LL<<30; else if(match[3] == "Ti") mult = 1LL<<40; else if(match[3] == "Pi") mult = 1LL<<50; else if(match[3] == "Ei") mult = 1LL<<60; else if(match[3] == "k") mult = 1'000LL; else if(match[3] == "M") mult = 1'000'000LL; else if(match[3] == "G") mult = 1'000'000'000LL; else if(match[3] == "T") mult = 1'000'000'000'000LL; else if(match[3] == "P") mult = 1'000'000'000'000'000LL; else if(match[3] == "E") mult = 1'000'000'000'000'000'000LL; bytes = d * mult; } std::ostream& operator<<(std::ostream& os) const { return FormatStream(os); } std::ostream& FormatStream(std::ostream& oss, bool si = false) const { oss << std::setprecision(3); if (si) { if (bytes < 1'000LL) oss << bytes << " B"; else if (bytes < 1'000'000LL) oss << (bytes * 1. / 1000LL) << " kB"; else if (bytes < 1'000'000'000LL) oss << (bytes * 1. / 1000'000LL) << " MB"; else if (bytes < 1'000'000'000'000LL) oss << (bytes * 1. / 1000'000'000LL) << " GB"; else if (bytes < 1'000'000'000'000'000LL) oss << (bytes * 1. / 1000'000'000'000LL) << " TB"; else if (bytes < 1'000'000'000'000'000'000LL) oss << (bytes * 1. / 1000'000'000'000'000LL) << " PB"; else oss << (bytes * 1. / 1000'000'000'000'000'000LL) << " EB"; } else { if (bytes < 1LL<<10) oss << bytes << " B"; else if (bytes < 1LL<<20) oss << (bytes * 1. / (1LL << 10)) << " kiB"; else if (bytes < 1LL<<30) oss << (bytes * 1. / (1LL << 20)) << " MiB"; else if (bytes < 1LL<<40) oss << (bytes * 1. / (1LL << 30)) << " GiB"; else if (bytes < 1LL<<50) oss << (bytes * 1. / (1LL << 40)) << " TiB"; else if (bytes < 1LL<<60) oss << (bytes * 1. / (1LL << 50)) << " PiB"; else oss << (bytes * 1. / (1LL << 60)) << " EiB"; } return oss; } [[nodiscard]] std::string Format(bool si = false) const { std::ostringstream oss; FormatStream(oss, si); return oss.str(); } constexpr operator size_t() const { return bytes; } operator std::string() const { return Format(); } }; // bytes only with integer inline ByteSize operator"" _B(unsigned long long int num){ return ByteSize(num); } // floating-point numbers, like 5.5_kB inline ByteSize operator"" _kiB(long double num) { return ByteSize((1LL<<10) * num); } inline ByteSize operator"" _MiB(long double num) { return ByteSize((1LL<<20) * num); } inline ByteSize operator"" _GiB(long double num) { return ByteSize((1LL<<30) * num); } inline ByteSize operator"" _TiB(long double num) { return ByteSize((1LL<<40) * num); } inline ByteSize operator"" _PiB(long double num) { return ByteSize((1LL<<50) * num); } inline ByteSize operator"" _kB(long double num) { return ByteSize(1'000LL * num); } inline ByteSize operator"" _MB(long double num) { return ByteSize(1'000'000LL * num); } inline ByteSize operator"" _GB(long double num) { return ByteSize(1'000'000'000LL * num); } inline ByteSize operator"" _TB(long double num) { return ByteSize(1'000'000'000'000LL * num); } inline ByteSize operator"" _PB(long double num) { return ByteSize(1'000'000'000'000'000LL * num); } // repeated for integer literals so that e.g. 5_kB works inline ByteSize operator"" _kiB(unsigned long long int num) { return ByteSize((1LL<<10) * num); } inline ByteSize operator"" _MiB(unsigned long long int num) { return ByteSize((1LL<<20) * num); } inline ByteSize operator"" _GiB(unsigned long long int num) { return ByteSize((1LL<<30) * num); } inline ByteSize operator"" _TiB(unsigned long long int num) { return ByteSize((1LL<<40) * num); } inline ByteSize operator"" _PiB(unsigned long long int num) { return ByteSize((1LL<<50) * num); } inline ByteSize operator"" _kB(unsigned long long int num) { return ByteSize(1'000LL * num); } inline ByteSize operator"" _MB(unsigned long long int num) { return ByteSize(1'000'000LL * num); } inline ByteSize operator"" _GB(unsigned long long int num) { return ByteSize(1'000'000'000LL * num); } inline ByteSize operator"" _TB(unsigned long long int num) { return ByteSize(1'000'000'000'000LL * num); } inline ByteSize operator"" _PB(unsigned long long int num) { return ByteSize(1'000'000'000'000'000LL * num); } } template<> struct fmt::formatter { template constexpr auto parse(ParseContext& ctx) { return ctx.begin(); } template auto format(const openVulkanoCpp::ByteSize& bs, FormatContext& ctx) { return format_to(ctx.out(), "{}", bs.Format()); } };