From 1ff23c2965a324617513114fff2bf7f505e97ccf Mon Sep 17 00:00:00 2001
From: Michael Osipov <1983-01-06@gmx.net>
Date: Sat, 30 Jul 2016 23:37:38 +0200
Subject: [PATCH 2/2] size_trunc_len(): drastically simplify function by
applying autoscale from size_trunc()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This function was used to scale according to the supplied length. Now, it will
scale at most to 8 characters by passing the size to size_trunc() and appending
to the supplied buffer.
It is important to note that small buffers to be bigger than it appears because
they store bytes and non-Latin scripts need more than one byte with UTF-8 to
encode them, e.g., 1023 МиБ in Russian requires 11 bytes + null terminator.
---
lib/util.c | 101 +++-------------------------------------------
src/filemanager/filegui.c | 6 ++-
src/filemanager/info.c | 12 +++---
src/filemanager/panel.c | 9 +++--
4 files changed, 22 insertions(+), 106 deletions(-)
diff --git a/lib/util.c b/lib/util.c
index 8de5314..6e2cd83 100644
a
|
b
|
size_trunc_sep (uintmax_t size, gboolean use_si) |
425 | 425 | void |
426 | 426 | size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si) |
427 | 427 | { |
428 | | /* Avoid taking power for every file. */ |
429 | | /* *INDENT-OFF* */ |
430 | | static const uintmax_t power10[] = { |
431 | | /* we hope that size of uintmax_t is 4 bytes at least */ |
432 | | 1ULL, |
433 | | 10ULL, |
434 | | 100ULL, |
435 | | 1000ULL, |
436 | | 10000ULL, |
437 | | 100000ULL, |
438 | | 1000000ULL, |
439 | | 10000000ULL, |
440 | | 100000000ULL, |
441 | | 1000000000ULL |
442 | | /* maximum value of uintmax_t (in case of 4 bytes) is |
443 | | 4294967295 |
444 | | */ |
445 | | #if SIZEOF_UINTMAX_T == 8 |
446 | | , |
447 | | 10000000000ULL, |
448 | | 100000000000ULL, |
449 | | 1000000000000ULL, |
450 | | 10000000000000ULL, |
451 | | 100000000000000ULL, |
452 | | 1000000000000000ULL, |
453 | | 10000000000000000ULL, |
454 | | 100000000000000000ULL, |
455 | | 1000000000000000000ULL, |
456 | | 10000000000000000000ULL |
457 | | /* maximum value of uintmax_t (in case of 8 bytes) is |
458 | | 18447644073710439615 |
459 | | */ |
460 | | #endif |
461 | | }; |
462 | | /* *INDENT-ON* */ |
463 | | static const char *const suffix[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", NULL }; |
464 | | static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL }; |
465 | | |
466 | | const char *const *sfx = use_si ? suffix_lc : suffix; |
467 | 428 | int j = 0; |
| 429 | const char *y; |
468 | 430 | |
469 | | if (len == 0) |
470 | | len = 9; |
471 | | #if SIZEOF_UINTMAX_T == 8 |
472 | | /* 20 decimal digits are required to represent 8 bytes */ |
473 | | else if (len > 19) |
474 | | len = 19; |
475 | | #else |
476 | | /* 10 decimal digits are required to represent 4 bytes */ |
477 | | else if (len > 9) |
478 | | len = 9; |
479 | | #endif |
| 431 | for (j = 0; j < units; j++) |
| 432 | size *= 1024; /* Scale to bytes */ |
480 | 433 | |
481 | | /* |
482 | | * recalculate from 1024 base to 1000 base if units>0 |
483 | | * We can't just multiply by 1024 - that might cause overflow |
484 | | * if uintmax_t type is too small |
485 | | */ |
486 | | if (use_si) |
487 | | for (j = 0; j < units; j++) |
488 | | { |
489 | | uintmax_t size_remain; |
490 | | |
491 | | size_remain = ((size % 125) * 1024) / 1000; /* size mod 125, recalculated */ |
492 | | size /= 125; /* 128/125 = 1024/1000 */ |
493 | | size *= 128; /* This will convert size from multiple of 1024 to multiple of 1000 */ |
494 | | size += size_remain; /* Re-add remainder lost by division/multiplication */ |
495 | | } |
496 | | |
497 | | for (j = units; sfx[j] != NULL; j++) |
498 | | { |
499 | | if (size == 0) |
500 | | { |
501 | | if (j == units) |
502 | | { |
503 | | /* Empty files will print "0" even with minimal width. */ |
504 | | g_snprintf (buffer, len + 1, "%s", "0"); |
505 | | } |
506 | | else |
507 | | { |
508 | | /* Use "~K" or just "K" if len is 1. Use "B" for bytes. */ |
509 | | g_snprintf (buffer, len + 1, (len > 1) ? "~%s" : "%s", (j > 1) ? sfx[j - 1] : "B"); |
510 | | } |
511 | | break; |
512 | | } |
513 | | |
514 | | if (size < power10[len - (j > 0 ? 1 : 0)]) |
515 | | { |
516 | | g_snprintf (buffer, len + 1, "%" PRIuMAX "%s", size, sfx[j]); |
517 | | break; |
518 | | } |
519 | | |
520 | | /* Powers of 1000 or 1024, with rounding. */ |
521 | | if (use_si) |
522 | | size = (size + 500) / 1000; |
523 | | else |
524 | | size = (size + 512) >> 10; |
525 | | } |
| 434 | y = size_trunc (size, use_si); |
| 435 | g_strlcpy (buffer, y, len + 1); |
| 436 | return; |
526 | 437 | } |
527 | 438 | |
528 | 439 | /* --------------------------------------------------------------------------------------------- */ |
diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c
index 2b6871a..7165f0a 100644
a
|
b
|
file_progress_show_total (file_op_total_context_t * tctx, file_op_context_t * ct |
1013 | 1013 | |
1014 | 1014 | if (ui->total_bytes_label != NULL) |
1015 | 1015 | { |
1016 | | size_trunc_len (buffer2, 5, tctx->copied_bytes, 0, panels_options.kilobyte_si); |
| 1016 | size_trunc_len (buffer2, sizeof(buffer2) - 1, tctx->copied_bytes, 0, |
| 1017 | panels_options.kilobyte_si); |
1017 | 1018 | if (!ctx->progress_totals_computed) |
1018 | 1019 | g_snprintf (buffer, sizeof (buffer), _(" Total: %s "), buffer2); |
1019 | 1020 | else |
1020 | 1021 | { |
1021 | | size_trunc_len (buffer3, 5, ctx->progress_bytes, 0, panels_options.kilobyte_si); |
| 1022 | size_trunc_len (buffer3, sizeof(buffer3) - 1, ctx->progress_bytes, 0, |
| 1023 | panels_options.kilobyte_si); |
1022 | 1024 | g_snprintf (buffer, sizeof (buffer), _(" Total: %s/%s "), buffer2, buffer3); |
1023 | 1025 | } |
1024 | 1026 | |
diff --git a/src/filemanager/info.c b/src/filemanager/info.c
index cb5cf6a..eda600c 100644
a
|
b
|
info_show_info (WInfo * info) |
176 | 176 | tty_print_string (_("No space information")); |
177 | 177 | else |
178 | 178 | { |
179 | | char buffer1[6], buffer2[6]; |
| 179 | char buffer1[12], buffer2[12]; |
180 | 180 | |
181 | | size_trunc_len (buffer1, 5, myfs_stats.avail, 1, panels_options.kilobyte_si); |
182 | | size_trunc_len (buffer2, 5, myfs_stats.total, 1, panels_options.kilobyte_si); |
| 181 | size_trunc_len (buffer1, sizeof(buffer1) - 1, myfs_stats.avail, 1, |
| 182 | panels_options.kilobyte_si); |
| 183 | size_trunc_len (buffer2, sizeof(buffer2) - 1, myfs_stats.total, 1, |
| 184 | panels_options.kilobyte_si); |
183 | 185 | tty_printf (_("Free space: %s/%s (%d%%)"), buffer1, buffer2, |
184 | 186 | myfs_stats.total == 0 ? 0 : |
185 | 187 | (int) (100 * (long double) myfs_stats.avail / myfs_stats.total)); |
… |
… |
info_show_info (WInfo * info) |
232 | 234 | else |
233 | 235 | #endif |
234 | 236 | { |
235 | | char buffer[10]; |
236 | | size_trunc_len (buffer, 9, st.st_size, 0, panels_options.kilobyte_si); |
| 237 | char buffer[12]; |
| 238 | size_trunc_len (buffer, sizeof(buffer) - 1, st.st_size, 0, panels_options.kilobyte_si); |
237 | 239 | tty_printf (_("Size: %s"), buffer); |
238 | 240 | #ifdef HAVE_STRUCT_STAT_ST_BLOCKS |
239 | 241 | tty_printf (ngettext (" (%ld block)", " (%ld blocks)", |
diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c
index 38e740a..b176be9 100644
a
|
b
|
static panel_field_t panel_fields[] = { |
195 | 195 | } |
196 | 196 | , |
197 | 197 | { |
198 | | "size", 7, FALSE, J_RIGHT, |
| 198 | "size", 8, FALSE, J_RIGHT, |
199 | 199 | /* TRANSLATORS: one single character to represent 'size' sort mode */ |
200 | 200 | /* TRANSLATORS: no need to translate 'sort', it's just a context prefix */ |
201 | 201 | N_("sort|s"), |
… |
… |
static panel_field_t panel_fields[] = { |
205 | 205 | } |
206 | 206 | , |
207 | 207 | { |
208 | | "bsize", 7, FALSE, J_RIGHT, |
| 208 | "bsize", 8, FALSE, J_RIGHT, |
209 | 209 | "", |
210 | 210 | N_("Block Size"), FALSE, FALSE, |
211 | 211 | string_file_size_brief, |
… |
… |
string_file_size (file_entry_t * fe, int len) |
515 | 515 | format_device_number (buffer, len + 1, fe->st.st_rdev); |
516 | 516 | else |
517 | 517 | #endif |
518 | | size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si); |
| 518 | size_trunc_len (buffer, (unsigned int) (len + 3), fe->st.st_size, 0, |
| 519 | panels_options.kilobyte_si); |
519 | 520 | |
520 | 521 | return buffer; |
521 | 522 | } |
… |
… |
show_free_space (const WPanel * panel) |
1154 | 1155 | if (myfs_stats.avail != 0 || myfs_stats.total != 0) |
1155 | 1156 | { |
1156 | 1157 | const Widget *w = CONST_WIDGET (panel); |
1157 | | char buffer1[6], buffer2[6], tmp[BUF_SMALL]; |
| 1158 | char buffer1[12], buffer2[12], tmp[BUF_SMALL]; |
1158 | 1159 | |
1159 | 1160 | size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1, |
1160 | 1161 | panels_options.kilobyte_si); |