summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorExplorer09 <explorer09@gmail.com>2023-12-25 19:17:29 +0800
committerBenBE <BenBE@geshi.org>2023-12-29 16:50:03 +0100
commite9cf230aa04689047ac95d1fe0613800d71934d9 (patch)
tree12de5374b5c144e1405460d498e241ae4d00bb15
parentc845b79ea7e9f384ca77064ea0bee16661b135f2 (diff)
Row_printKBytes() improvements
* Allow the maximum value of "15.9Z" ((2^64 - 2) KiB) to be printed. (The previous version supports the maximum of "99.9P" (99.9 PiB) before the printing format goes weird.) * Print up to 2 fraction digits for values between "9.76G" (10000 MiB) and "9.99G" (< 10 GiB), "9.76T" and "9.99T", and so on. Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
-rw-r--r--Row.c170
-rw-r--r--Row.h6
2 files changed, 99 insertions, 77 deletions
diff --git a/Row.c b/Row.c
index e268837d..1a1b727d 100644
--- a/Row.c
+++ b/Row.c
@@ -190,94 +190,116 @@ RowField RowField_keyAt(const Settings* settings, int at) {
return COMM;
}
-void Row_printBytes(RichString* str, unsigned long long number, bool coloring) {
+void Row_printKBytes(RichString* str, unsigned long long number, bool coloring) {
char buffer[16];
int len;
- int largeNumberColor = coloring ? CRT_colors[LARGE_NUMBER] : CRT_colors[PROCESS];
- int megabytesColor = coloring ? CRT_colors[PROCESS_MEGABYTES] : CRT_colors[PROCESS];
- int gigabytesColor = coloring ? CRT_colors[PROCESS_GIGABYTES] : CRT_colors[PROCESS];
- int shadowColor = coloring ? CRT_colors[PROCESS_SHADOW] : CRT_colors[PROCESS];
- int baseColor = CRT_colors[PROCESS];
+ int color = CRT_colors[PROCESS];
+ int nextUnitColor = CRT_colors[PROCESS];
- if (number == ULLONG_MAX) {
- //Invalid number
- RichString_appendAscii(str, shadowColor, " N/A ");
+ const int colors[4] = {
+ [0] = CRT_colors[PROCESS],
+ [1] = CRT_colors[PROCESS_MEGABYTES],
+ [2] = CRT_colors[PROCESS_GIGABYTES],
+ [3] = CRT_colors[LARGE_NUMBER]
+ };
+
+ if (number == ULLONG_MAX)
+ goto invalidNumber;
+
+ if (coloring) {
+ color = colors[0];
+ nextUnitColor = colors[1];
+ }
+
+ if (number < 1000) {
+ // Plain number, no markings
+ len = xSnprintf(buffer, sizeof(buffer), "%5u ", (unsigned int)number);
+ RichString_appendnAscii(str, color, buffer, len);
return;
}
- number /= ONE_K;
+ if (number < 100000) {
+ // 2 digits for M, 3 digits for K
+ len = xSnprintf(buffer, sizeof(buffer), "%2u", (unsigned int)(number / 1000));
+ RichString_appendnAscii(str, nextUnitColor, buffer, len);
+ len = xSnprintf(buffer, sizeof(buffer), "%03u ", (unsigned int)(number % 1000));
+ RichString_appendnAscii(str, color, buffer, len);
+ return;
+ }
- if (number < 1000) {
- //Plain number, no markings
- len = xSnprintf(buffer, sizeof(buffer), "%5llu ", number);
- RichString_appendnAscii(str, baseColor, buffer, len);
- } else if (number < 100000) {
- //2 digit MB, 3 digit KB
- len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / 1000);
- RichString_appendnAscii(str, megabytesColor, buffer, len);
- number %= 1000;
- len = xSnprintf(buffer, sizeof(buffer), "%03llu ", number);
- RichString_appendnAscii(str, baseColor, buffer, len);
- } else if (number < 1000 * ONE_K) {
- //3 digit MB
- number /= ONE_K;
- len = xSnprintf(buffer, sizeof(buffer), "%4lluM ", number);
- RichString_appendnAscii(str, megabytesColor, buffer, len);
- } else if (number < 10000 * ONE_K) {
- //1 digit GB, 3 digit MB
- number /= ONE_K;
- len = xSnprintf(buffer, sizeof(buffer), "%1llu", number / 1000);
- RichString_appendnAscii(str, gigabytesColor, buffer, len);
- number %= 1000;
- len = xSnprintf(buffer, sizeof(buffer), "%03lluM ", number);
- RichString_appendnAscii(str, megabytesColor, buffer, len);
- } else if (number < 100 * ONE_M) {
- //2 digit GB, 1 digit MB
- len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / ONE_M);
- RichString_appendnAscii(str, gigabytesColor, buffer, len);
- number = (number % ONE_M) * 10 / ONE_M;
- len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number);
- RichString_appendnAscii(str, megabytesColor, buffer, len);
- RichString_appendAscii(str, gigabytesColor, "G ");
- } else if (number < 1000 * ONE_M) {
- //3 digit GB
- number /= ONE_M;
- len = xSnprintf(buffer, sizeof(buffer), "%4lluG ", number);
- RichString_appendnAscii(str, gigabytesColor, buffer, len);
- } else if (number < 10000ULL * ONE_M) {
- //1 digit TB, 3 digit GB
- number /= ONE_M;
- len = xSnprintf(buffer, sizeof(buffer), "%1llu", number / 1000);
- RichString_appendnAscii(str, largeNumberColor, buffer, len);
- number %= 1000;
- len = xSnprintf(buffer, sizeof(buffer), "%03lluG ", number);
- RichString_appendnAscii(str, gigabytesColor, buffer, len);
- } else if (number < 100ULL * ONE_G) {
- //2 digit TB, 1 digit GB
- len = xSnprintf(buffer, sizeof(buffer), "%2llu", number / ONE_G);
- RichString_appendnAscii(str, largeNumberColor, buffer, len);
- number = (number % ONE_G) * 10 / ONE_G;
- len = xSnprintf(buffer, sizeof(buffer), ".%1llu", number);
- RichString_appendnAscii(str, gigabytesColor, buffer, len);
- RichString_appendAscii(str, largeNumberColor, "T ");
- } else if (number < 10000ULL * ONE_G) {
- //3 digit TB or 1 digit PB, 3 digit TB
- number /= ONE_G;
- len = xSnprintf(buffer, sizeof(buffer), "%4lluT ", number);
- RichString_appendnAscii(str, largeNumberColor, buffer, len);
+ // 100000 KiB (97.6 MiB) or greater. A unit prefix would be added.
+ const size_t maxUnitIndex = (sizeof(number) * CHAR_BIT - 1) / 10 + 1;
+ const bool canOverflow = maxUnitIndex >= ARRAYSIZE(unitPrefixes);
+
+ size_t i = 1;
+ int prevUnitColor;
+ // Convert KiB to (1/100) of MiB
+ unsigned long long hundredths = (number / 256) * 25 + (number % 256) * 25 / 256;
+ while (true) {
+ if (canOverflow && i >= ARRAYSIZE(unitPrefixes))
+ goto invalidNumber;
+
+ prevUnitColor = color;
+ color = nextUnitColor;
+
+ if (coloring && i + 1 < ARRAYSIZE(colors))
+ nextUnitColor = colors[i + 1];
+
+ if (hundredths < 1000000)
+ break;
+
+ hundredths /= ONE_K;
+ i++;
+ }
+
+ number = hundredths / 100;
+ hundredths %= 100;
+ if (number < 100) {
+ if (number < 10) {
+ // 1 digit + decimal point + 2 digits
+ // "9.76G", "9.99G", "9.76T", "9.99T", etc.
+ len = xSnprintf(buffer, sizeof(buffer), "%1u", (unsigned int)number);
+ RichString_appendnAscii(str, color, buffer, len);
+ len = xSnprintf(buffer, sizeof(buffer), ".%02u", (unsigned int)hundredths);
+ } else {
+ // 2 digits + decimal point + 1 digit
+ // "97.6M", "99.9M", "10.0G", "99.9G", etc.
+ len = xSnprintf(buffer, sizeof(buffer), "%2u", (unsigned int)number);
+ RichString_appendnAscii(str, color, buffer, len);
+ len = xSnprintf(buffer, sizeof(buffer), ".%1u", (unsigned int)hundredths / 10);
+ }
+ RichString_appendnAscii(str, prevUnitColor, buffer, len);
+ len = xSnprintf(buffer, sizeof(buffer), "%c ", unitPrefixes[i]);
+ } else if (number < 1000) {
+ // 3 digits
+ // "100M", "999M", "100G", "999G", etc.
+ len = xSnprintf(buffer, sizeof(buffer), "%4u%c ", (unsigned int)number, unitPrefixes[i]);
} else {
- //2 digit PB and above
- len = xSnprintf(buffer, sizeof(buffer), "%4.1lfP ", (double)number / ONE_T);
- RichString_appendnAscii(str, largeNumberColor, buffer, len);
+ // 1 digit + 3 digits
+ // "1000M", "9999M", "1000G", "9999G", etc.
+ assert(number < 10000);
+
+ len = xSnprintf(buffer, sizeof(buffer), "%1u", (unsigned int)number / 1000);
+ RichString_appendnAscii(str, nextUnitColor, buffer, len);
+ len = xSnprintf(buffer, sizeof(buffer), "%03u%c ", (unsigned int)number % 1000, unitPrefixes[i]);
}
+ RichString_appendnAscii(str, color, buffer, len);
+ return;
+
+invalidNumber:
+ if (coloring)
+ color = CRT_colors[PROCESS_SHADOW];
+
+ RichString_appendAscii(str, color, " N/A ");
+ return;
}
-void Row_printKBytes(RichString* str, unsigned long long number, bool coloring) {
+void Row_printBytes(RichString* str, unsigned long long number, bool coloring) {
if (number == ULLONG_MAX)
- Row_printBytes(str, ULLONG_MAX, coloring);
+ Row_printKBytes(str, ULLONG_MAX, coloring);
else
- Row_printBytes(str, number * ONE_K, coloring);
+ Row_printKBytes(str, number / ONE_K, coloring);
}
void Row_printCount(RichString* str, unsigned long long number, bool coloring) {
diff --git a/Row.h b/Row.h
index 951f998c..f67c6103 100644
--- a/Row.h
+++ b/Row.h
@@ -142,12 +142,12 @@ void Row_setPidColumnWidth(pid_t maxPid);
/* Sets the size of the UID column based on the passed UID */
void Row_setUidColumnWidth(uid_t maxUid);
+/* Takes number in kibibytes (base 1024). Prints 6 columns. */
+void Row_printKBytes(RichString* str, unsigned long long number, bool coloring);
+
/* Takes number in bytes (base 1024). Prints 6 columns. */
void Row_printBytes(RichString* str, unsigned long long number, bool coloring);
-/* Takes number in kilo bytes (base 1024). Prints 6 columns. */
-void Row_printKBytes(RichString* str, unsigned long long number, bool coloring);
-
/* Takes number as count (base 1000). Prints 12 columns. */
void Row_printCount(RichString* str, unsigned long long number, bool coloring);

© 2014-2024 Faster IT GmbH | imprint | privacy policy