Skip to content

Commit acc3548

Browse files
eworm-desteadytao
andcommitted
human-readable: calculate numbers in a loop
This drops a lot of `else if` blocks and extends units by "E" (Exa), which is 2^60 and thus the last to fit into int64. Co-authored-by: Zen Dodd <mail@steadytao.com>
1 parent 5553271 commit acc3548

2 files changed

Lines changed: 23 additions & 23 deletions

File tree

lib/compat.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -173,34 +173,34 @@ char *do_big_num(int64 num, int human_flag, const char *fract)
173173
static unsigned int n;
174174
char *s;
175175
int len, negated;
176+
uint64_t abs_num;
176177

177178
if (human_flag && !number_separator)
178179
(void)get_number_separator();
179180

180181
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
182+
abs_num = num < 0 ? 0 - (uint64_t)num : (uint64_t)num;
181183

182184
if (human_flag > 1) {
183-
int mult = human_flag == 2 ? 1000 : 1024;
184-
if (num >= mult || num <= -mult) {
185-
double dnum = (double)num / mult;
186-
char units;
187-
if (num < 0)
188-
dnum = -dnum;
189-
if (dnum < mult)
190-
units = 'K';
191-
else if ((dnum /= mult) < mult)
192-
units = 'M';
193-
else if ((dnum /= mult) < mult)
194-
units = 'G';
195-
else if ((dnum /= mult) < mult)
196-
units = 'T';
197-
else {
198-
dnum /= mult;
199-
units = 'P';
185+
unsigned int mult = human_flag == 2 ? 1000 : 1024;
186+
187+
if (abs_num >= mult) {
188+
const char* units = " KMGTPE";
189+
uint64_t powi = 1;
190+
191+
for (;;) {
192+
if (abs_num / mult < powi)
193+
break;
194+
195+
if (units[1] == '\0')
196+
break;
197+
198+
powi *= mult;
199+
++units;
200200
}
201-
if (num < 0)
202-
dnum = -dnum;
203-
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
201+
202+
snprintf(bufs[n], sizeof bufs[0], "%.2f%c",
203+
(double) num / powi, *units);
204204
return bufs[n];
205205
}
206206
}

rsync.1.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3352,9 +3352,9 @@ expand it.
33523352
digits) by specifying the `--no-human-readable` (`--no-h`) option.
33533353

33543354
The unit letters that are appended in levels 2 and 3 are: `K` (kilo), `M`
3355-
(mega), `G` (giga), `T` (tera), or `P` (peta). For example, a 1234567-byte
3356-
file would output as 1.23M in level-2 (assuming that a period is your local
3357-
decimal point).
3355+
(mega), `G` (giga), `T` (tera), `P` (peta) or `E` (exa). For example, a
3356+
1234567-byte file would output as 1.23M in level-2 (assuming that a
3357+
period is your local decimal point).
33583358

33593359
Backward compatibility note: versions of rsync prior to 3.1.0 do not
33603360
support human-readable level 1, and they default to level 0. Thus,

0 commit comments

Comments
 (0)