From 5911b052dc526898d4963680fe83c6e2dc67e55f Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 13 May 2023 12:01:09 +0200 Subject: [PATCH] libluna: Add more options to to_dynamic_unit() Also, make the output look more like how it is on linux. --- apps/ls.cpp | 8 +++++--- libluna/include/luna/Units.h | 9 ++++++++- libluna/src/Units.cpp | 36 +++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/apps/ls.cpp b/apps/ls.cpp index 093db522..7dd3c4c6 100644 --- a/apps/ls.cpp +++ b/apps/ls.cpp @@ -63,6 +63,7 @@ Result luna_main(int argc, char** argv) bool show_almost_all { false }; bool long_list { false }; bool human_readable { false }; + bool si { false }; os::ArgumentParser parser; parser.add_description("List files contained in a directory (defaults to '.', the current directory)"_sv); @@ -73,6 +74,7 @@ Result luna_main(int argc, char** argv) parser.add_switch_argument(long_list, 'l', ""_sv, "use a long listing format"_sv); parser.add_switch_argument(human_readable, 'h', "human-readable"_sv, "with -l, show human-readable sizes e.g. 2KiB, 6GiB"_sv); + parser.add_switch_argument(si, ' ', "si"_sv, "same as -h, but show sizes in powers of 10"_sv); parser.parse(argc, argv); Vector files; @@ -116,15 +118,15 @@ Result luna_main(int argc, char** argv) TRY(find_user_and_group(st, owner, group)); - if (!human_readable) + if (!human_readable && !si) { os::println("%6o %u %4s %4s %10lu %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(), st.st_size, file.chars()); } else { - auto size = TRY(to_dynamic_unit(st.st_size)); - os::println("%6o %u %4s %4s %10s %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(), + auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false)); + os::println("%6o %u %4s %4s %6s %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(), size.chars(), file.chars()); } } diff --git a/libluna/include/luna/Units.h b/libluna/include/luna/Units.h index dccc8010..6f6d3a46 100644 --- a/libluna/include/luna/Units.h +++ b/libluna/include/luna/Units.h @@ -2,4 +2,11 @@ #include #include -Result to_dynamic_unit(usize value); +enum class Unit : usize +{ + SI = 1000, + Binary = 1024 +}; + +Result to_dynamic_unit(usize value, usize round_after = 1000, bool separate = true, Unit unit = Unit::Binary, + bool display_unit = true); diff --git a/libluna/src/Units.cpp b/libluna/src/Units.cpp index fd05f853..652dca1e 100644 --- a/libluna/src/Units.cpp +++ b/libluna/src/Units.cpp @@ -1,18 +1,44 @@ #include +#include #include #include #include -Result to_dynamic_unit(usize value) +Result to_dynamic_unit(usize value, usize round_after, bool separate, Unit unit, bool display_unit) { - if (value < 1024) { return String::format("%zu bytes"_sv, value); } + const usize multiplier = (usize)unit; + if (value < multiplier) { return String::format("%zu%s"_sv, value, display_unit ? " bytes" : ""); } + + bool si = unit == Unit::SI; const char* unit_prefixes = "KMGTPE"; - while (value > (1024 * 1024)) + if (si) unit_prefixes = "kMGTPE"; + while (value > (multiplier * multiplier)) { - value /= 1024; + value /= multiplier; unit_prefixes++; } - return String::format("%zu.%zu %ciB"_sv, value / 1024, (value % 1024) / 103, *unit_prefixes); + const usize divider = (si ? 100 : 103); + + usize fixed = value / multiplier; + usize rest = (value % multiplier) / divider; + bool round = fixed >= round_after; + + if (round) + { + if (value % multiplier) fixed++; + return String::format("%zu%s%c%s"_sv, fixed, separate ? " " : "", *unit_prefixes, + display_unit ? (si ? "B" : "iB") : ""); + } + + if ((value % multiplier) % divider) rest++; + if (rest > 9) + { + rest = 0; + fixed++; + } + + return String::format("%zu.%zu%s%c%s"_sv, fixed, rest, separate ? " " : "", *unit_prefixes, + display_unit ? (si ? "B" : "iB") : ""); }