repart: tweak byte value output

So far, when outputing information about copy progress we'd suppress the
digit after the dot if it is zero. That makes the progress bar a bit
"jumpy", because sometimes there are two more character cells used than
other times. Let's just always output one digit after the dot here
hence, to avoid this.
This commit is contained in:
Lennart Poettering
2025-09-19 16:46:07 +02:00
parent 222dcf3bc2
commit 2f5fb752a6
4 changed files with 39 additions and 27 deletions
+2 -1
View File
@@ -39,7 +39,8 @@ char* format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) {
(t / table[i + 1].factor * 10 / table[n - 1].factor) % 10 :
(t * 10 / table[i].factor) % 10;
if (FLAGS_SET(flag, FORMAT_BYTES_BELOW_POINT) && remainder > 0)
if (FLAGS_SET(flag, FORMAT_BYTES_ALWAYS_POINT) ||
(FLAGS_SET(flag, FORMAT_BYTES_BELOW_POINT) && remainder > 0))
(void) snprintf(buf, l,
"%" PRIu64 ".%" PRIu64 "%s",
t / table[i].factor,
+6 -4
View File
@@ -64,9 +64,10 @@ assert_cc(sizeof(gid_t) == sizeof(uint32_t));
#endif
typedef enum {
FORMAT_BYTES_USE_IEC = 1 << 0,
FORMAT_BYTES_BELOW_POINT = 1 << 1,
FORMAT_BYTES_TRAILING_B = 1 << 2,
FORMAT_BYTES_USE_IEC = 1 << 0, /* use base 1024 rather than 1000 */
FORMAT_BYTES_BELOW_POINT = 1 << 1, /* show one digit after the point, if non-zero */
FORMAT_BYTES_ALWAYS_POINT = 1 << 2, /* show one digit after the point, always */
FORMAT_BYTES_TRAILING_B = 1 << 3, /* suffix the expression with a "B" for "bytes" */
} FormatBytesFlag;
#define FORMAT_BYTES_MAX 16U
@@ -82,6 +83,7 @@ static inline char* format_bytes(char *buf, size_t l, uint64_t t) {
* see C11 §6.5.2.5, and
* https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
#define FORMAT_BYTES(t) format_bytes((char[FORMAT_BYTES_MAX]){}, FORMAT_BYTES_MAX, t)
#define FORMAT_BYTES_FULL(t, flag) format_bytes_full((char[FORMAT_BYTES_MAX]){}, FORMAT_BYTES_MAX, t, flag)
#define FORMAT_BYTES_FULL(t, flags) format_bytes_full((char[FORMAT_BYTES_MAX]){}, FORMAT_BYTES_MAX, t, flags)
#define FORMAT_BYTES_WITH_POINT(t) format_bytes_full((char[FORMAT_BYTES_MAX]){}, FORMAT_BYTES_MAX, t, FORMAT_BYTES_USE_IEC|FORMAT_BYTES_ALWAYS_POINT|FORMAT_BYTES_TRAILING_B)
#define FORMAT_BYTES_CGROUP_PROTECTION(t) (t == CGROUP_LIMIT_MAX ? "infinity" : FORMAT_BYTES(t))
+5 -5
View File
@@ -5493,9 +5493,9 @@ static int progress_bytes(uint64_t n_bytes, uint64_t bps, void *userdata) {
strna(p->copy_blocks_path),
glyph(GLYPH_ARROW_RIGHT),
strna(p->definition_path),
FORMAT_BYTES(p->copy_blocks_done),
FORMAT_BYTES(p->copy_blocks_size),
FORMAT_BYTES(bps));
FORMAT_BYTES_WITH_POINT(p->copy_blocks_done),
FORMAT_BYTES_WITH_POINT(p->copy_blocks_size),
FORMAT_BYTES_WITH_POINT(bps));
else
(void) draw_progress_barf(
percent,
@@ -5503,8 +5503,8 @@ static int progress_bytes(uint64_t n_bytes, uint64_t bps, void *userdata) {
strna(p->copy_blocks_path),
glyph(GLYPH_ARROW_RIGHT),
strna(p->definition_path),
FORMAT_BYTES(p->copy_blocks_done),
FORMAT_BYTES(p->copy_blocks_size));
FORMAT_BYTES_WITH_POINT(p->copy_blocks_done),
FORMAT_BYTES_WITH_POINT(p->copy_blocks_size));
p->last_percent = percent;
+26 -17
View File
@@ -28,32 +28,41 @@ assert_cc(DECIMAL_STR_MAX(signed char) == STRLEN("-127")+1);
assert_cc(DECIMAL_STR_MAX(unsigned char) == STRLEN("255")+1);
assert_cc(CONST_MAX(DECIMAL_STR_MAX(int8_t), STRLEN("xxx")) == 5);
static void test_format_bytes_one(uint64_t val, bool trailing_B, const char *iec_with_p, const char *iec_without_p,
const char *si_with_p, const char *si_without_p) {
static void test_format_bytes_one(
uint64_t val,
bool trailing_B,
const char *iec_with_p,
const char *iec_without_p,
const char *iec_always_p,
const char *si_with_p,
const char *si_without_p,
const char *si_always_p) {
char buf[FORMAT_BYTES_MAX];
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_with_p);
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_without_p);
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_ALWAYS_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_always_p);
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), si_with_p);
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, trailing_B ? FORMAT_BYTES_TRAILING_B : 0), si_without_p);
ASSERT_STREQ(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_ALWAYS_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), si_always_p);
}
TEST(format_bytes) {
test_format_bytes_one(900, true, "900B", "900B", "900B", "900B");
test_format_bytes_one(900, false, "900", "900", "900", "900");
test_format_bytes_one(1023, true, "1023B", "1023B", "1K", "1K");
test_format_bytes_one(1023, false, "1023", "1023", "1K", "1K");
test_format_bytes_one(1024, true, "1K", "1K", "1K", "1K");
test_format_bytes_one(1024, false, "1K", "1K", "1K", "1K");
test_format_bytes_one(1100, true, "1K", "1K", "1.1K", "1K");
test_format_bytes_one(1500, true, "1.4K", "1K", "1.5K", "1K");
test_format_bytes_one(UINT64_C(3)*1024*1024, true, "3M", "3M", "3.1M", "3M");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024, true, "3G", "3G", "3.2G", "3G");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024, true, "3T", "3T", "3.2T", "3T");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024, true, "3P", "3P", "3.3P", "3P");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024*1024, true, "3E", "3E", "3.4E", "3E");
test_format_bytes_one(UINT64_MAX, true, NULL, NULL, NULL, NULL);
test_format_bytes_one(UINT64_MAX, false, NULL, NULL, NULL, NULL);
test_format_bytes_one(900, true, "900B", "900B", "900B", "900B", "900B", "900B");
test_format_bytes_one(900, false, "900", "900", "900", "900", "900", "900");
test_format_bytes_one(1023, true, "1023B", "1023B", "1023B", "1K", "1K", "1.0K");
test_format_bytes_one(1023, false, "1023", "1023", "1023", "1K", "1K", "1.0K");
test_format_bytes_one(1024, true, "1K", "1K", "1.0K", "1K", "1K", "1.0K");
test_format_bytes_one(1024, false, "1K", "1K", "1.0K", "1K", "1K", "1.0K");
test_format_bytes_one(1100, true, "1K", "1K", "1.0K", "1.1K", "1K", "1.1K");
test_format_bytes_one(1500, true, "1.4K", "1K", "1.4K", "1.5K", "1K", "1.5K");
test_format_bytes_one(UINT64_C(3)*1024*1024, true, "3M", "3M", "3.0M", "3.1M", "3M", "3.1M");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024, true, "3G", "3G", "3.0G", "3.2G", "3G", "3.2G");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024, true, "3T", "3T", "3.0T", "3.2T", "3T", "3.2T");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024, true, "3P", "3P", "3.0P", "3.3P", "3P", "3.3P");
test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024*1024, true, "3E", "3E", "3.0E", "3.4E", "3E", "3.4E");
test_format_bytes_one(UINT64_MAX, true, NULL, NULL, NULL, NULL, NULL, NULL);
test_format_bytes_one(UINT64_MAX, false, NULL, NULL, NULL, NULL, NULL, NULL);
}
DEFINE_TEST_MAIN(LOG_INFO);