summaryrefslogtreecommitdiffstats
path: root/Meter.c
diff options
context:
space:
mode:
authorExplorer09 <explorer09@gmail.com>2023-10-27 18:34:47 +0800
committerBenBE <BenBE@geshi.org>2023-11-24 09:51:25 +0100
commit5751bafb8db06b843a9a79e100751cfcadc09f90 (patch)
tree8771ae3f5c4068b7cf1db3b84de3240b3da1dfbe /Meter.c
parente34a9fcc8cda01e4a58f59b4a9d990eda8effd60 (diff)
Rewrite Meter_humanUnit() to accept floating point value
Since Meter_humanUnit() is often called with floating point values in Meter objects, rewrite the function to let it process `double` type natively, and save floating point to integer casts. The rewritten function: * Allows higher orders of magnitude including 'R' and 'Q', and addresses infinity. (The previous version has a maximum value of (2^64 - 1) representing 16 ZiB.) * Rounds values when they are in intervals (99.9, 100) and (9.99, 10), and displays them with correct precision (number of fraction digits). * Produces assertion error on negative and NaN values (undefined behavior). Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
Diffstat (limited to 'Meter.c')
-rw-r--r--Meter.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/Meter.c b/Meter.c
index 12c8c941..64e88071 100644
--- a/Meter.c
+++ b/Meter.c
@@ -51,32 +51,40 @@ Meter* Meter_new(const Machine* host, unsigned int param, const MeterClass* type
return this;
}
-int Meter_humanUnit(char* buffer, unsigned long int value, size_t size) {
- const char* prefix = "KMGTPEZY";
- unsigned long int powi = 1;
- unsigned int powj = 1, precision = 2;
-
- for (;;) {
- if (value / 1024 < powi)
- break;
-
- if (prefix[1] == '\0')
+/* Converts 'value' in kibibytes into a human readable string.
+ Example output strings: "0K", "1023K", "98.7M" and "1.23G" */
+int Meter_humanUnit(char* buffer, double value, size_t size) {
+ size_t i = 0;
+
+ assert(value >= 0.0);
+ while (value >= ONE_K) {
+ if (i >= ARRAYSIZE(unitPrefixes) - 1) {
+ if (value > 9999.0) {
+ return snprintf(buffer, size, "inf");
+ }
break;
+ }
- powi *= 1024;
- ++prefix;
+ value /= ONE_K;
+ ++i;
}
- if (*prefix == 'K')
- precision = 0;
+ int precision = 0;
- for (; precision > 0; precision--) {
- powj *= 10;
- if (value / powi < powj)
- break;
+ if (i > 0) {
+ // Fraction digits for mebibytes and above
+ precision = value <= 99.9 ? (value <= 9.99 ? 2 : 1) : 0;
+
+ // Round up if 'value' is in range (99.9, 100) or (9.99, 10)
+ if (precision < 2) {
+ double limit = precision == 1 ? 10.0 : 100.0;
+ if (value < limit) {
+ value = limit;
+ }
+ }
}
- return snprintf(buffer, size, "%.*f%c", precision, (double) value / powi, *prefix);
+ return snprintf(buffer, size, "%.*f%c", precision, value, unitPrefixes[i]);
}
void Meter_delete(Object* cast) {

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