Serenity Operating System
at master 112 lines 3.5 kB view raw
1/* 2 * Copyright (c) 2020-2022, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <AK/DeprecatedString.h> 9#include <AK/NumberFormat.h> 10#include <AK/NumericLimits.h> 11#include <AK/StringView.h> 12 13namespace AK { 14 15// FIXME: Remove this hackery once printf() supports floats. 16static DeprecatedString number_string_with_one_decimal(u64 number, u64 unit, StringView suffix) 17{ 18 constexpr auto max_unit_size = NumericLimits<u64>::max() / 10; 19 VERIFY(unit < max_unit_size); 20 21 auto integer_part = number / unit; 22 auto decimal_part = (number % unit) * 10 / unit; 23 return DeprecatedString::formatted("{}.{} {}", integer_part, decimal_part, suffix); 24} 25 26DeprecatedString human_readable_quantity(u64 quantity, HumanReadableBasedOn based_on, StringView unit) 27{ 28 u64 size_of_unit = based_on == HumanReadableBasedOn::Base2 ? 1024 : 1000; 29 constexpr auto unit_prefixes = AK::Array { "", "K", "M", "G", "T", "P", "E" }; 30 auto full_unit_suffix = [&](int index) { 31 auto binary_infix = (based_on == HumanReadableBasedOn::Base2 && index != 0) ? "i"sv : ""sv; 32 return DeprecatedString::formatted("{}{}{}", 33 unit_prefixes[index], binary_infix, unit); 34 }; 35 36 auto size_of_current_unit = size_of_unit; 37 38 if (quantity < size_of_unit) 39 return DeprecatedString::formatted("{} {}", quantity, full_unit_suffix(0)); 40 41 for (size_t i = 1; i < unit_prefixes.size() - 1; i++) { 42 auto suffix = full_unit_suffix(i); 43 if (quantity < size_of_unit * size_of_current_unit) { 44 return number_string_with_one_decimal(quantity, size_of_current_unit, suffix); 45 } 46 47 size_of_current_unit *= size_of_unit; 48 } 49 50 return number_string_with_one_decimal(quantity, 51 size_of_current_unit, full_unit_suffix(unit_prefixes.size() - 1)); 52} 53 54DeprecatedString human_readable_size(u64 size, HumanReadableBasedOn based_on) 55{ 56 return human_readable_quantity(size, based_on, "B"sv); 57} 58 59DeprecatedString human_readable_size_long(u64 size) 60{ 61 if (size < 1 * KiB) 62 return DeprecatedString::formatted("{} bytes", size); 63 else 64 return DeprecatedString::formatted("{} ({} bytes)", human_readable_size(size), size); 65} 66 67DeprecatedString human_readable_time(i64 time_in_seconds) 68{ 69 auto days = time_in_seconds / 86400; 70 time_in_seconds = time_in_seconds % 86400; 71 72 auto hours = time_in_seconds / 3600; 73 time_in_seconds = time_in_seconds % 3600; 74 75 auto minutes = time_in_seconds / 60; 76 time_in_seconds = time_in_seconds % 60; 77 78 StringBuilder builder; 79 80 if (days > 0) 81 builder.appendff("{} day{} ", days, days == 1 ? "" : "s"); 82 83 if (hours > 0) 84 builder.appendff("{} hour{} ", hours, hours == 1 ? "" : "s"); 85 86 if (minutes > 0) 87 builder.appendff("{} minute{} ", minutes, minutes == 1 ? "" : "s"); 88 89 builder.appendff("{} second{}", time_in_seconds, time_in_seconds == 1 ? "" : "s"); 90 91 return builder.to_deprecated_string(); 92} 93 94DeprecatedString human_readable_digital_time(i64 time_in_seconds) 95{ 96 auto hours = time_in_seconds / 3600; 97 time_in_seconds = time_in_seconds % 3600; 98 99 auto minutes = time_in_seconds / 60; 100 time_in_seconds = time_in_seconds % 60; 101 102 StringBuilder builder; 103 104 if (hours > 0) 105 builder.appendff("{:02}:", hours); 106 builder.appendff("{:02}:", minutes); 107 builder.appendff("{:02}", time_in_seconds); 108 109 return builder.to_deprecated_string(); 110} 111 112}