tests: added funny 'secondary progress' and final reports
[libha.git] / src / pbar.c
blobd7b3d096b0d7c10dc52be5b28f5b96821f7210ce
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
7 #include <sys/ioctl.h>
9 #include "pbar.h"
12 static int pbar_tty; // fd or -1
15 static __attribute__((constructor)) void _ctor_pbar (void) {
16 if (isatty(STDOUT_FILENO)) pbar_tty = STDOUT_FILENO;
17 else if (isatty(STDERR_FILENO)) pbar_tty = STDERR_FILENO;
18 else pbar_tty = -1;
22 static int get_tty_width (void) {
23 if (pbar_tty >= 0) {
24 struct winsize ws;
25 if (ioctl(pbar_tty, TIOCGWINSZ, &ws) != 0 || ws.ws_col < 2) return 79;
26 return ws.ws_col-1;
28 return 79;
32 void pbar_u2s (char *dest, uint64_t i) {
33 char num[128], *p = num+sizeof(num);
34 int cnt = 3;
35 *(--p) = 0;
36 for (;;) {
37 *(--p) = (i%10)+'0';
38 if ((i /= 10) == 0) break;
39 if (--cnt == 0) { *(--p) = ','; cnt = 3; }
41 strcpy(dest, p);
45 /* return number of dots */
46 static int pbar_draw_ex (uint64_t cur, uint64_t total, uint64_t taken, int silent) {
47 if (pbar_tty >= 0) {
48 char cstr[128], tstr[128], wstr[1025];
49 int slen, wdt;
50 if (cur > total) cur = total;
51 if (taken > total) taken = total;
52 pbar_u2s(cstr, cur);
53 pbar_u2s(tstr, total);
54 wdt = get_tty_width();
55 if (wdt > 1024) wdt = 1024;
56 /* numbers */
57 sprintf(wstr, "\r[%*s/%s]", strlen(tstr), cstr, tstr);
58 slen = strlen(wstr);
59 if (!silent) write(pbar_tty, wstr, slen);
60 slen += 7;
61 if (slen+1 <= wdt) {
62 /* dots */
63 int pos;
64 int dc = (cur >= total ? wdt-slen : ((uint64_t)(wdt-slen))*cur/total);
65 int tc = (taken >= total ? wdt-slen : ((uint64_t)(wdt-slen))*taken/total);
66 strcpy(wstr, " [");
67 pos = strlen(wstr);
68 if (cur == 0) dc = -1;
69 if (silent) return ((tc+1)<<16)|(dc+1); /* just return number of dots */
70 for (int f = 0; f < wdt-slen; ++f) {
71 if (f <= dc) {
72 wstr[pos++] = (f <= tc ? ':' : '.');
73 } else {
74 wstr[pos++] = (f <= tc ? '*' : ' ');
77 wstr[pos++] = ']';
78 write(pbar_tty, wstr, pos);
79 sprintf(cstr, "%4d%%", (int)(total > 0 ? (uint64_t)100*cur/total : 100));
80 write(pbar_tty, cstr, strlen(cstr));
83 return 0;
87 void pbar_draw (uint64_t cur, uint64_t total, uint64_t taken) { pbar_draw_ex(cur, total, taken, 0); }
88 int pbar_dot_count (uint64_t cur, uint64_t total, uint64_t taken) { return pbar_draw_ex(cur, total, taken, 1); }
91 void pbar_clear (void) {
92 static const char *cstr = "\r\x1b[K";
93 if (pbar_tty >= 0) write(pbar_tty, cstr, strlen(cstr));
97 void pbar_newline (void) {
98 if (pbar_tty >= 0) write(pbar_tty, "\r\n", 2); /* "\r\n" for strange tty modes */