summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArda Cinar <kuzux92@gmail.com>2022-12-10 12:01:10 +0300
committerSam Atkins <atkinssj@gmail.com>2023-01-02 20:11:18 +0000
commitc8fadff9b1c5d7cde8d041893aca565dc1af7d15 (patch)
tree3442bcfb87d9db56d86dbd9330c30c4699ff69e1
parent3e924e2a374744862d40a2eba6684e939ee751f1 (diff)
downloadserenity-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.cpp46
-rw-r--r--AK/NumberFormat.h4
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;