On Fri, 27 Nov 2015 15:35:21 +0100 Bernhard Nortmann <[email protected]> wrote:
> Signed-off-by: Bernhard Nortmann <[email protected]> > --- > progress.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- > progress.h | 2 ++ > 2 files changed, 51 insertions(+), 3 deletions(-) > > diff --git a/progress.c b/progress.c > index 5b24198..05d8f8b 100644 > --- a/progress.c > +++ b/progress.c > @@ -28,16 +28,48 @@ inline double gettime(void) > return tv.tv_sec + (double)tv.tv_usec / 1000000.; > } > > +/* Calculate transfer rate (in bytes per second) */ > +inline double rate(size_t transferred, double elapsed) > +{ > + if (elapsed > 0) > + return (double)transferred / elapsed; > + return 0.; > +} > + > +/* Estimate remaining time ("ETA") for given transfer rate */ > +inline double estimate(size_t remaining, double rate) > +{ > + if (rate > 0) > + return (double)remaining / rate; > + return 0.; > +} > + > +/* Return ETA (in seconds) as string, formatted to minutes and seconds */ > +const char *format_ETA(double remaining) > +{ > + static char result[6] = ""; > + > + int seconds = remaining + 0.5; /* simplistic round() */ > + if (seconds >= 0 && seconds < 6000) { > + snprintf(result, sizeof(result), > + "%02d:%02d", seconds / 60, seconds % 60); > + return result; > + } > + return "--:--"; > +} > + > /* Private progress state variable */ > > typedef struct { > progress_cb_t callback; > size_t total; > size_t done; > + double start; /* start point (timestamp) for rate and ETA calculation */ > } progress_private_t; > > static progress_private_t progress = { > .callback = NULL, > + .start = 0. > }; > > /* 'External' API */ > @@ -47,6 +79,7 @@ void progress_start(progress_cb_t callback, size_t > expected_total) > progress.callback = callback; > progress.total = expected_total; > progress.done = 0; > + progress.start = gettime(); /* reset start time */ > } > > /* Update progress status, passing information to the callback function. */ > @@ -57,19 +90,32 @@ void progress_update(size_t bytes_done) > progress.callback(progress.total, progress.done); > } > > +/* Return relative / "elapsed" time, since progress_start() */ > +static inline double progress_elapsed(void) > +{ > + if (progress.start != 0.) > + return gettime() - progress.start; > + return 0.; > +} > + > /* Callback function implementing a simple progress bar written to stdout */ > void progress_bar(size_t total, size_t done) > { > - static const int WIDTH = 60; /* # of characters to use for progress bar > */ > + static const int WIDTH = 48; /* # of characters to use for progress bar > */ > > float ratio = total > 0 ? (float)done / total : 0; > int i, pos = WIDTH * ratio; > + double speed = rate(done, progress_elapsed()); > + double eta = estimate(total - done, speed); > > printf("\r%3.0f%% [", ratio * 100); /* current percentage */ > for (i = 0; i < pos; i++) putchar('='); > for (i = pos; i < WIDTH; i++) putchar(' '); > - printf("] "); > + if (done < total) > + printf("]%6.1f kB/s, ETA %s ", kilo(speed), format_ETA(eta)); > + else > + /* transfer complete, output totals plus a newline */ > + printf("] %5.0f kB, %6.1f kB/s\n", kilo(done), kilo(speed)); > > - if (done >= total) putchar('\n'); /* output newline when complete */ > fflush(stdout); > } > diff --git a/progress.h b/progress.h > index 6c4dc7f..5eb767f 100644 > --- a/progress.h > +++ b/progress.h > @@ -28,6 +28,8 @@ typedef void (*progress_cb_t)(size_t total, size_t done); > #define kibi(value) ((double)value / 1024.) /* binary prefix "Ki", "K" */ > > double gettime(void); > +double rate(size_t transferred, double elapsed); > +double estimate(size_t remaining, double rate); > > void progress_start(progress_cb_t callback, size_t expected_total); > void progress_update(size_t bytes_done); Reviewed-by: Siarhei Siamashka <[email protected]> -- Best regards, Siarhei Siamashka -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
