summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2024-04-07 16:00:07 +0200
committerPřemysl Eric Janouch <p@janouch.name>2024-04-07 16:00:21 +0200
commit9ce6f477167c598c122ab6f558ac8a95ece9c5c3 (patch)
treed9e6ad7777e8b6d314b9ce4790673ebd9fbd040a
parentc9662f1a7bef8ccb6013dcc2a4a15b58f1d27a4b (diff)
downloadsdn-9ce6f477167c598c122ab6f558ac8a95ece9c5c3.tar.gz
sdn-9ce6f477167c598c122ab6f558ac8a95ece9c5c3.tar.xz
sdn-9ce6f477167c598c122ab6f558ac8a95ece9c5c3.zip
Use more precise filesizes
The behaviour differs from GNU `ls -lh` in that we use binary units, meaning we get 1023 before 1.0K rather than 999 before 1.0K, which is nonetheless still four characters wide.
-rw-r--r--sdn.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/sdn.cpp b/sdn.cpp
index 9496475..48f425c 100644
--- a/sdn.cpp
+++ b/sdn.cpp
@@ -640,6 +640,25 @@ fun ls_format (const entry &e, bool for_target) -> chtype {
return format;
}
+fun suffixize (off_t size, unsigned shift, wchar_t suffix, std::wstring &out)
+ -> bool {
+ // Prevent implementation-defined and undefined behaviour
+ if (size < 0 || shift >= sizeof size * 8)
+ return false;
+
+ off_t divided = size >> shift;
+ if (divided >= 10) {
+ out.assign (std::to_wstring (divided)).append (1, suffix);
+ return true;
+ } else if (divided > 0) {
+ unsigned times_ten = size / double (off_t (1) << shift) * 10.0;
+ out.assign ({L'0' + wchar_t (times_ten / 10), L'.',
+ L'0' + wchar_t (times_ten % 10), suffix});
+ return true;
+ }
+ return false;
+}
+
fun make_entry (const struct dirent *f) -> entry {
entry e;
e.filename = f->d_name;
@@ -690,11 +709,12 @@ fun make_entry (const struct dirent *f) -> entry {
? apply_attrs (grp->second, 0)
: apply_attrs (to_wstring (info.st_gid), 0);
- auto size = to_wstring (info.st_size);
- if (info.st_size >> 40) size = to_wstring (info.st_size >> 40) + L"T";
- else if (info.st_size >> 30) size = to_wstring (info.st_size >> 30) + L"G";
- else if (info.st_size >> 20) size = to_wstring (info.st_size >> 20) + L"M";
- else if (info.st_size >> 10) size = to_wstring (info.st_size >> 10) + L"K";
+ std::wstring size;
+ if (!suffixize (info.st_size, 40, L'T', size) &&
+ !suffixize (info.st_size, 30, L'G', size) &&
+ !suffixize (info.st_size, 20, L'M', size) &&
+ !suffixize (info.st_size, 10, L'K', size))
+ size = to_wstring (info.st_size);
e.cols[entry::SIZE] = apply_attrs (size, 0);
wchar_t buf[32] = L"";