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)19 void 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)35 void 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)82 void progress_end(void)
83 {
84 	printf("\n");
85 }
86