]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
progress: expand to use 6 characters per size
authorDaniel Stenberg <daniel@haxx.se>
Fri, 3 Oct 2025 08:51:46 +0000 (10:51 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 3 Oct 2025 12:08:41 +0000 (14:08 +0200)
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

lib/progress.c

index fdae3194c55daa08da09e6461360892b859e9805..2fa0fa122886e1463a34274b46680e773b08019f 100644 (file)
@@ -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 */