summaryrefslogtreecommitdiffstats
path: root/libsmartcols/samples/continuous.c
blob: 7db3f8464d810b76041f600823107f24ffac6b90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2016 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>

#include "c.h"
#include "nls.h"
#include "strutils.h"
#include "xalloc.h"

#include "libsmartcols.h"

#define TIME_PERIOD	3.0	/* seconds */

enum { COL_NUM, COL_DATA, COL_TIME };

static double time_diff(struct timeval *a, struct timeval *b)
{
	return (a->tv_sec - b->tv_sec) + (a->tv_usec - b->tv_usec) / 1E6;
}

/* add columns to the @tb */
static void setup_columns(struct libscols_table *tb)
{
	scols_table_enable_maxout(tb, 1);
	if (!scols_table_new_column(tb, "#NUM", 0.1, SCOLS_FL_RIGHT))
		goto fail;
	if (!scols_table_new_column(tb, "DATA", 0.7, 0))
		goto fail;
	if (!scols_table_new_column(tb, "TIME", 0.2, 0))
		goto fail;
	return;
fail:
	scols_unref_table(tb);
	err(EXIT_FAILURE, "failed to create output columns");
}

static struct libscols_line *add_line(struct libscols_table *tb, size_t i)
{
	char *p;
	struct libscols_line *ln = scols_table_new_line(tb, NULL);

	if (!ln)
		err(EXIT_FAILURE, "failed to create output line");

	xasprintf(&p, "%zu", i);
	if (scols_line_refer_data(ln, COL_NUM, p))
		goto fail;

	xasprintf(&p, "data-%02zu-%02zu-%02zu-end", i + 1, i + 2, i + 3);
	if (scols_line_refer_data(ln, COL_DATA, p))
		goto fail;

	return ln;
fail:
	scols_unref_table(tb);
	err(EXIT_FAILURE, "failed to create output line");
}

int main(int argc, char *argv[])
{
	struct libscols_table *tb;
	size_t i;
	const size_t timecellsz = sizeof(stringify_value(UINT_MAX));
	struct timeval last;

	scols_init_debug(0);

	tb = scols_new_table();
	if (!tb)
		err(EXIT_FAILURE, "failed to create output table");

	setup_columns(tb);
	gettimeofday(&last, NULL);

	for (i = 0; i < 10; i++) {
		struct libscols_line *line;
		struct timeval now;
		int done = 0;
		char *timecell = xmalloc( timecellsz );

		line = add_line(tb, i);

		/* Make a reference from cell data to the buffer, then we can
		 * update cell data without any interaction with libsmartcols
		 */
		if (scols_line_refer_data(line, COL_TIME, timecell) != 0)
			err(EXIT_FAILURE, "failed to add data to table");

		do {
			double diff;

			gettimeofday(&now, NULL);
			diff = time_diff(&now, &last);

			if (now.tv_sec == last.tv_sec + (long) TIME_PERIOD)
				done = 1;
			else
				xusleep(100000);

			/* update "TIME" cell data */
			snprintf(timecell, timecellsz, "%f [%3d%%]", diff,
				done ? 100 : (int)(diff / (TIME_PERIOD / 100.0)));

			/* Note that libsmartcols don't print \n for last line
			 * in the table, but if you print a line somewhere in
			 * the midle of the table you need
			 *
			 *    scols_table_enable_nolinesep(tb, !done);
			 *
			 * to disable line breaks. In this example it's
			 * unnecessary as we print the latest line only.
			 */

			/* print the line */
			scols_table_print_range(tb, line, NULL);

			if (!done) {
				/* terminal is waiting for \n, fflush() to force output */
				fflush(scols_table_get_stream(tb));
				/* move to the begin of the line */
				fputc('\r', scols_table_get_stream(tb));
			} else
				fputc('\n', scols_table_get_stream(tb));
		} while (!done);

		last = now;
	}

	scols_unref_table(tb);
	return EXIT_SUCCESS;
}