| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <limits.h> |
| #include <time.h> |
| |
| static unsigned long progress_max; |
| static unsigned int progress_pcent; |
| static unsigned long progress_n_upd; |
| static unsigned int progress_prevsec; |
| static struct timespec progress_start; |
| |
| #define PROGRESS_CHARS 50 |
| |
| void progress_init(unsigned long count) |
| { |
| unsigned int i; |
| |
| progress_max = count; |
| progress_pcent = 0; |
| progress_n_upd = ULONG_MAX; |
| progress_prevsec = UINT_MAX; |
| |
| printf("\r["); |
| for (i = 0; i < PROGRESS_CHARS; i++) |
| printf(" "); |
| printf("] 0%%"); |
| fflush(stdout); |
| clock_gettime(CLOCK_MONOTONIC, &progress_start);} |
| |
| void progress_tick(unsigned long cur) |
| { |
| unsigned int pcent, i, pos, sec; |
| struct timespec now; |
| |
| pcent = (cur * 100) / progress_max; |
| if (progress_pcent == pcent && cur < progress_n_upd && |
| cur < progress_max) |
| return; |
| progress_pcent = pcent; |
| pos = (pcent * PROGRESS_CHARS) / 101; |
| clock_gettime(CLOCK_MONOTONIC, &now); |
| |
| printf("\r["); |
| for (i = 0; i <= pos; i++) |
| printf("="); |
| for (; i < PROGRESS_CHARS; i++) |
| printf(" "); |
| printf("] %u%%", pcent); |
| |
| sec = now.tv_sec - progress_start.tv_sec; |
| if (sec >= 5 && pcent > 0) { |
| unsigned int persec = cur / sec; |
| unsigned int rem_sec; |
| |
| if (!persec) |
| persec = 1; |
| progress_n_upd = cur + persec; |
| rem_sec = ((sec * 100) + (pcent / 2)) / pcent - sec; |
| if (rem_sec > progress_prevsec) |
| rem_sec = progress_prevsec; |
| progress_prevsec = rem_sec; |
| if (rem_sec < 60) |
| printf(" ETA:%us ", rem_sec); |
| else { |
| printf(" ETA:%u:%02d:%02u ", |
| rem_sec / 3600, |
| (rem_sec / 60) % 60, |
| rem_sec % 60); |
| } |
| } |
| |
| fflush(stdout); |
| } |
| |
| void progress_end(void) |
| { |
| printf("\n"); |
| } |