Skip to content

Commit 19134d1

Browse files
committed
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.
1 parent bad790d commit 19134d1

2 files changed

Lines changed: 21 additions & 21 deletions

File tree

lib/compat.c

Lines changed: 18 additions & 18 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+
int64 pos_num;
176177

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

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

182184
if (human_flag > 1) {
183185
int mult = human_flag == 2 ? 1000 : 1024;
186+
184187
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';
188+
const char* units = " KMGTPE";
189+
int64 powi = 1;
190+
191+
for (;;) {
192+
if (pos_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
@@ -3342,9 +3342,9 @@ expand it.
33423342
digits) by specifying the `--no-human-readable` (`--no-h`) option.
33433343

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

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

0 commit comments

Comments
 (0)