1 #include <inttypes.h> 2 #include <limits.h> 3 #include <stdint.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <time.h> 8 9 #include "progress.h" 10 11 static uint64_t progress_max; 12 static uint64_t progress_pcent; 13 static uint64_t progress_n_upd; 14 static time_t progress_prevsec; 15 static struct timespec progress_start; 16 17 #define PROGRESS_CHARS 50 18 progress_init(uint64_t count)19void progress_init(uint64_t count) 20 { 21 unsigned int i; 22 23 progress_max = count; 24 progress_pcent = 0; 25 progress_n_upd = ULONG_MAX; 26 progress_prevsec = ULONG_MAX; 27 28 printf("\r["); 29 for (i = 0; i < PROGRESS_CHARS; i++) 30 printf(" "); 31 printf("] 0%%"); 32 fflush(stdout); 33 clock_gettime(CLOCK_MONOTONIC, &progress_start);} 34 progress_tick(uint64_t cur)35void progress_tick(uint64_t cur) 36 { 37 unsigned int i, pos; 38 struct timespec now; 39 uint64_t pcent; 40 double sec; 41 42 pcent = (cur * 100) / progress_max; 43 if (progress_pcent == pcent && cur < progress_n_upd && 44 cur < progress_max) 45 return; 46 progress_pcent = pcent; 47 pos = (pcent * PROGRESS_CHARS) / 101; 48 clock_gettime(CLOCK_MONOTONIC, &now); 49 50 printf("\r["); 51 for (i = 0; i <= pos; i++) 52 printf("="); 53 for (; i < PROGRESS_CHARS; i++) 54 printf(" "); 55 printf("] %" PRIu64 "%%", pcent); 56 57 sec = difftime(now.tv_sec, progress_start.tv_sec); 58 if (sec >= 5 && pcent > 0) { 59 uint64_t persec = cur / sec; 60 uint64_t rem_sec; 61 62 if (!persec) 63 persec = 1; 64 progress_n_upd = cur + persec; 65 rem_sec = ((sec * 100) + (pcent / 2)) / pcent - sec; 66 if (rem_sec > progress_prevsec) 67 rem_sec = progress_prevsec; 68 progress_prevsec = rem_sec; 69 if (rem_sec < 60) 70 printf(" ETA:%" PRIu64 "s ", rem_sec); 71 else { 72 printf(" ETA:%" PRIu64 ":%02" PRIu64 ":%02" PRIu64 " ", 73 rem_sec / 3600, 74 (rem_sec / 60) % 60, 75 rem_sec % 60); 76 } 77 } 78 79 fflush(stdout); 80 } 81 progress_end(void)82void progress_end(void) 83 { 84 printf("\n"); 85 } 86