diff options
author | Arda Cinar <kuzux92@gmail.com> | 2022-12-10 12:01:10 +0300 |
---|---|---|
committer | Sam Atkins <atkinssj@gmail.com> | 2023-01-02 20:11:18 +0000 |
commit | c8fadff9b1c5d7cde8d041893aca565dc1af7d15 (patch) | |
tree | 3442bcfb87d9db56d86dbd9330c30c4699ff69e1 | |
parent | 3e924e2a374744862d40a2eba6684e939ee751f1 (diff) | |
download | serenity-c8fadff9b1c5d7cde8d041893aca565dc1af7d15.zip |
AK: Add a human_readable_quantity helper to NumberFormat.h
This can be used for displaying large quantities that are not measured
in bytes in a more human-readable format.
-rw-r--r-- | AK/NumberFormat.cpp | 46 | ||||
-rw-r--r-- | AK/NumberFormat.h | 4 |
2 files changed, 36 insertions, 14 deletions
diff --git a/AK/NumberFormat.cpp b/AK/NumberFormat.cpp index bf83b0efe3..fd31ee01a6 100644 --- a/AK/NumberFormat.cpp +++ b/AK/NumberFormat.cpp @@ -4,32 +4,50 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/DeprecatedString.h> #include <AK/NumberFormat.h> +#include <AK/StringView.h> namespace AK { // FIXME: Remove this hackery once printf() supports floats. -static DeprecatedString number_string_with_one_decimal(u64 number, u64 unit, char const* suffix) +static DeprecatedString number_string_with_one_decimal(u64 number, u64 unit, StringView suffix) { int decimal = (number % unit) * 10 / unit; return DeprecatedString::formatted("{}.{} {}", number / unit, decimal, suffix); } +DeprecatedString human_readable_quantity(u64 quantity, StringView unit) +{ + constexpr u64 size_of_unit = 1024; + constexpr auto unit_prefixes = AK::Array { "", "K", "M", "G", "T", "P", "E" }; + auto full_unit_suffix = [&](int index) { + auto binary_infix = (size_of_unit == 1024 && index != 0) ? "i"sv : ""sv; + return DeprecatedString::formatted("{}{}{}", + unit_prefixes[index], binary_infix, unit); + }; + + auto size_of_current_unit = size_of_unit; + + if (quantity < size_of_unit) + return DeprecatedString::formatted("{} {}", quantity, full_unit_suffix(0)); + + for (size_t i = 1; i < unit_prefixes.size() - 1; i++) { + auto suffix = full_unit_suffix(i); + if (quantity < size_of_unit * size_of_current_unit) { + return number_string_with_one_decimal(quantity, size_of_current_unit, suffix); + } + + size_of_current_unit *= size_of_unit; + } + + return number_string_with_one_decimal(quantity, + size_of_current_unit, full_unit_suffix(unit_prefixes.size() - 1)); +} + DeprecatedString human_readable_size(u64 size) { - if (size < 1 * KiB) - return DeprecatedString::formatted("{} B", size); - if (size < 1 * MiB) - return number_string_with_one_decimal(size, KiB, "KiB"); - if (size < 1 * GiB) - return number_string_with_one_decimal(size, MiB, "MiB"); - if (size < 1 * TiB) - return number_string_with_one_decimal(size, GiB, "GiB"); - if (size < 1 * PiB) - return number_string_with_one_decimal(size, TiB, "TiB"); - if (size < 1 * EiB) - return number_string_with_one_decimal(size, PiB, "PiB"); - return number_string_with_one_decimal(size, EiB, "EiB"); + return human_readable_quantity(size, "B"sv); } DeprecatedString human_readable_size_long(u64 size) diff --git a/AK/NumberFormat.h b/AK/NumberFormat.h index a6aa710c67..32965f51ad 100644 --- a/AK/NumberFormat.h +++ b/AK/NumberFormat.h @@ -10,7 +10,10 @@ namespace AK { +// TODO: Add an optional base here for binary vs si units DeprecatedString human_readable_size(u64 size); +DeprecatedString human_readable_quantity(u64 quantity, StringView unit = "B"sv); + DeprecatedString human_readable_size_long(u64 size); DeprecatedString human_readable_time(i64 time_in_seconds); DeprecatedString human_readable_digital_time(i64 time_in_seconds); @@ -19,6 +22,7 @@ DeprecatedString human_readable_digital_time(i64 time_in_seconds); #if USING_AK_GLOBALLY using AK::human_readable_digital_time; +using AK::human_readable_quantity; using AK::human_readable_size; using AK::human_readable_size_long; using AK::human_readable_time; |