From: Daniel Stenberg Date: Fri, 3 Oct 2025 08:51:46 +0000 (+0200) Subject: progress: expand to use 6 characters per size X-Git-Tag: rc-8_17_0-2~266 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4b8278fb3d0a43fecf66caa23ad1cd28f759de71;p=thirdparty%2Fcurl.git progress: expand to use 6 characters per size Previously the progress meter used a maximum of five digits+letter in the progress meter output: up to 99999 bytes and then 9999k, 9999M etc. The output then used two spaces after the size between the next field in the display. This new approach uses one letter more with only one space in between the fields. It makes it possible to show up to 999999 bytes and then 99999k, 99999M etc. The function uses a single decimal when outputting a value less than 1000 in any unit. Like 999.9M. Closes #18828 --- diff --git a/lib/progress.c b/lib/progress.c index fdae3194c5..2fa0fa1228 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -63,54 +63,37 @@ static void time2str(char *r, curl_off_t seconds) } /* The point of this function would be to return a string of the input data, - but never longer than 5 columns (+ one zero byte). + but never longer than 6 columns (+ one zero byte). Add suffix k, M, G when suitable... */ -static char *max5data(curl_off_t bytes, char *max5) +static char *max6data(curl_off_t bytes, char *max6) { -#define ONE_KILOBYTE (curl_off_t)1024 -#define ONE_MEGABYTE (1024 * ONE_KILOBYTE) -#define ONE_GIGABYTE (1024 * ONE_MEGABYTE) -#define ONE_TERABYTE (1024 * ONE_GIGABYTE) -#define ONE_PETABYTE (1024 * ONE_TERABYTE) - - if(bytes < 100000) - msnprintf(max5, 6, "%5" FMT_OFF_T, bytes); - - else if(bytes < 10000 * ONE_KILOBYTE) - msnprintf(max5, 6, "%4" FMT_OFF_T "k", bytes/ONE_KILOBYTE); - - else if(bytes < 100 * ONE_MEGABYTE) - /* 'XX.XM' is good as long as we are less than 100 megs */ - msnprintf(max5, 6, "%2" FMT_OFF_T ".%0" - FMT_OFF_T "M", bytes/ONE_MEGABYTE, - (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/10) ); - - else if(bytes < 10000 * ONE_MEGABYTE) - /* 'XXXXM' is good until we are at 10000MB or above */ - msnprintf(max5, 6, "%4" FMT_OFF_T "M", bytes/ONE_MEGABYTE); - - else if(bytes < 100 * ONE_GIGABYTE) - /* 10000 MB - 100 GB, we show it as XX.XG */ - msnprintf(max5, 6, "%2" FMT_OFF_T ".%0" - FMT_OFF_T "G", bytes/ONE_GIGABYTE, - (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/10) ); - - else if(bytes < 10000 * ONE_GIGABYTE) - /* up to 10000GB, display without decimal: XXXXG */ - msnprintf(max5, 6, "%4" FMT_OFF_T "G", bytes/ONE_GIGABYTE); - - else if(bytes < 10000 * ONE_TERABYTE) - /* up to 10000TB, display without decimal: XXXXT */ - msnprintf(max5, 6, "%4" FMT_OFF_T "T", bytes/ONE_TERABYTE); - - else - /* up to 10000PB, display without decimal: XXXXP */ - msnprintf(max5, 6, "%4" FMT_OFF_T "P", bytes/ONE_PETABYTE); - - /* 16384 petabytes (16 exabytes) is the maximum a 64-bit unsigned number can - hold, but our data type is signed so 8192PB will be the maximum. */ + /* a signed 64-bit value is 8192 petabytes maximum */ + const char unit[] = { 'k', 'M', 'G', 'T', 'P', 0 }; + int k = 0; + if(bytes < 1000000) { + msnprintf(max6, 7, "%5" CURL_FORMAT_CURL_OFF_T, bytes); + return max6; + } - return max5; + do { + curl_off_t nbytes = bytes / 1024; + if(nbytes < 1000) { + /* xxx.yU */ + msnprintf(max6, 7, "%3" CURL_FORMAT_CURL_OFF_T + ".%" CURL_FORMAT_CURL_OFF_T "%c", nbytes, + (bytes%1024) / (1024/10), unit[k]); + break; + } + else if(nbytes < 100000) { + /* xxxxxU */ + msnprintf(max6, 7, "%5" CURL_FORMAT_CURL_OFF_T "%c", nbytes, unit[k]); + break; + } + bytes = nbytes; + k++; + DEBUGASSERT(unit[k]); + } while(unit[k]); + return max6; } #endif @@ -503,7 +486,7 @@ static void pgrs_estimates(struct pgrs_dir *d, static void progress_meter(struct Curl_easy *data) { struct Progress *p = &data->progress; - char max5[6][10]; + char max6[6][7]; struct pgrs_estimate dl_estm; struct pgrs_estimate ul_estm; struct pgrs_estimate total_estm; @@ -561,21 +544,21 @@ static void progress_meter(struct Curl_easy *data) fprintf(data->set.err, "\r" - "%3" FMT_OFF_T " %s " - "%3" FMT_OFF_T " %s " - "%3" FMT_OFF_T " %s %s %s %s %s %s %s", + "%3" FMT_OFF_T " %s " + "%3" FMT_OFF_T " %s " + "%3" FMT_OFF_T " %s %s %s %s %s %s %s", total_estm.percent, /* 3 letters */ /* total % */ - max5data(total_expected_size, max5[2]), /* total size */ + max6data(total_expected_size, max6[2]), /* total size */ dl_estm.percent, /* 3 letters */ /* rcvd % */ - max5data(p->dl.cur_size, max5[0]), /* rcvd size */ + max6data(p->dl.cur_size, max6[0]), /* rcvd size */ ul_estm.percent, /* 3 letters */ /* xfer % */ - max5data(p->ul.cur_size, max5[1]), /* xfer size */ - max5data(p->dl.speed, max5[3]), /* avrg dl speed */ - max5data(p->ul.speed, max5[4]), /* avrg ul speed */ + max6data(p->ul.cur_size, max6[1]), /* xfer size */ + max6data(p->dl.speed, max6[3]), /* avrg dl speed */ + max6data(p->ul.speed, max6[4]), /* avrg ul speed */ time_total, /* 8 letters */ /* total time */ time_spent, /* 8 letters */ /* time spent */ time_left, /* 8 letters */ /* time left */ - max5data(p->current_speed, max5[5]) + max6data(p->current_speed, max6[5]) ); /* we flush the output stream to make it appear as soon as possible */