standalone test: fixed major bug
[libha.git] / src / pbar.c
blob7ddd93bd6f18e5090924e0173f1e8a27b77dd19d
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 static void i2n (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, 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 i2n(cstr, cur);
52 i2n(tstr, total);
53 wdt = get_tty_width();
54 if (wdt > 1024) wdt = 1024;
55 /* numbers */
56 sprintf(wstr, "\r[%*s/%s]", strlen(tstr), cstr, tstr);
57 slen = strlen(wstr);
58 if (!silent) write(pbar_tty, wstr, slen);
59 slen += 7;
60 if (slen+1 <= wdt) {
61 /* dots */
62 int dc = (cur >= total ? wdt-slen : ((uint64_t)(wdt-slen))*cur/total), pos;
63 strcpy(wstr, " [");
64 pos = strlen(wstr);
65 if (cur == 0) dc = -1;
66 if (silent) return dc+1; /* just return number of dots */
67 for (int f = 0; f < wdt-slen; ++f) wstr[pos++] = (f <= dc ? '.' : ' ');
68 wstr[pos++] = ']';
69 write(pbar_tty, wstr, pos);
70 sprintf(cstr, "%4d%%", (int)(total > 0 ? (uint64_t)100*cur/total : 100));
71 write(pbar_tty, cstr, strlen(cstr));
74 return 0;
78 void pbar_draw (uint64_t cur, uint64_t total) { pbar_draw_ex(cur, total, 0); }
79 int pbar_dot_count (uint64_t cur, uint64_t total) { return pbar_draw_ex(cur, total, 1); }
82 void pbar_clear (void) {
83 static const char *cstr = "\r\x1b[K";
84 if (pbar_tty >= 0) write(pbar_tty, cstr, strlen(cstr));