2 Copyright (c) 2020 Damjan Marion
4 Permission is hereby granted, free of charge, to any person obtaining
5 a copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and/or sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions:
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <vppinfra/format.h>
25 #include <vppinfra/format_table.h>
27 static table_text_attr_t default_title = {
28 .flags = TTAF_FG_COLOR_SET | TTAF_BOLD,
29 .fg_color = TTAC_YELLOW,
33 static table_text_attr_t default_body = {
37 static table_text_attr_t default_header_col = {
38 .flags = TTAF_FG_COLOR_SET,
39 .fg_color = TTAC_YELLOW,
43 static table_text_attr_t default_header_row = {
44 .flags = TTAF_FG_COLOR_SET | TTAF_BOLD,
45 .fg_color = TTAC_GREEN,
50 format_text_cell (table_t *t, u8 *s, table_cell_t *c, table_text_attr_t *def,
53 table_text_attr_t _a = {}, *a = &_a;
56 return format (s, t->no_ansi ? "" : "\x1b[0m");
58 clib_memcpy (a, def, sizeof (table_text_attr_t));
63 if (c->attr.flags & TTAF_FG_COLOR_SET)
65 a->fg_color = c->attr.fg_color;
66 a->flags |= TTAF_FG_COLOR_SET;
67 a->flags |= c->attr.flags & TTAF_FG_COLOR_BRIGHT;
70 if (c->attr.flags & TTAF_BG_COLOR_SET)
72 a->bg_color = c->attr.bg_color;
73 a->flags |= TTAF_BG_COLOR_SET;
74 a->flags |= c->attr.flags & TTAF_BG_COLOR_BRIGHT;
77 if (a->flags & TTAF_RESET)
80 if (a->flags & TTAF_BOLD)
83 if (a->flags & TTAF_DIM)
86 if (a->flags & TTAF_UNDERLINE)
89 if (a->flags & TTAF_FG_COLOR_SET)
91 (a->flags & TTAF_FG_COLOR_BRIGHT ? 90 : 30) + a->fg_color);
93 if (a->flags & TTAF_BG_COLOR_SET)
95 (a->flags & TTAF_BG_COLOR_BRIGHT ? 100 : 40) + a->bg_color);
99 s = format (s, "\x1b[");
100 for (int i = 0; i < vec_len (codes); i++)
101 s = format (s, "%s%u", i ? ";" : "", codes[i]);
108 table_text_attr_align_t align = c->attr.align;
109 if (align == TTAA_DEFAULT)
111 if (align == TTAA_LEFT)
112 fmt = format (fmt, "%%-%uv%c", size, 0);
113 else if (align == TTAA_CENTER)
114 fmt = format (fmt, "%%=%uv%c", size, 0);
116 fmt = format (fmt, "%%%uv%c", size, 0);
117 s = format (s, (char *) fmt, c->text);
119 return format (s, t->no_ansi ? "" : "\x1b[0m");
123 format_table (u8 *s, va_list *args)
125 table_t *t = va_arg (*args, table_t *);
126 table_cell_t title_cell = { .text = t->title };
128 for (int i = 0; i < vec_len (t->row_sizes); i++)
129 table_width += t->row_sizes[i];
133 table_text_attr_t *title_default;
135 t->default_title.as_u32 ? &t->default_title : &default_title;
136 s = format_text_cell (t, s, &title_cell, title_default, table_width);
137 s = format (s, "\n");
140 for (int c = 0; c < vec_len (t->cells); c++)
142 table_text_attr_t *col_default;
144 if (c < t->n_header_cols)
145 col_default = t->default_header_col.as_u32 ? &t->default_header_col :
149 t->default_body.as_u32 ? &t->default_body : &default_body;
151 for (int r = 0; r < vec_len (t->cells[c]); r++)
153 table_text_attr_t *row_default = col_default;
156 if (r < t->n_header_rows && c >= t->n_header_cols)
157 row_default = t->default_header_row.as_u32 ?
158 &t->default_header_row :
160 s = format_text_cell (t, s, &t->cells[c][r], row_default,
163 if (c + 1 < vec_len (t->cells))
164 s = format (s, "\n");
171 table_format_title (table_t *t, char *fmt, ...)
176 t->title = va_format (t->title, fmt, &va);
180 static table_cell_t *
181 table_get_cell (table_t *t, int c, int r)
183 c += t->n_header_cols;
184 r += t->n_header_rows;
186 /* grow table if needed */
187 vec_validate (t->cells, c);
188 for (int i = 0; i < vec_len (t->cells); i++)
189 vec_validate (t->cells[i], r);
190 return &t->cells[c][r];
194 table_format_cell (table_t *t, int c, int r, char *fmt, ...)
196 table_cell_t *cell = table_get_cell (t, c, r);
199 c += t->n_header_cols;
200 r += t->n_header_rows;
203 cell->text = va_format (t->cells[c][r].text, fmt, &va);
206 vec_validate (t->row_sizes, r);
207 t->row_sizes[r] = clib_max (t->row_sizes[r], vec_len (t->cells[c][r].text));
211 table_set_cell_align (table_t *t, int c, int r, table_text_attr_align_t a)
213 table_cell_t *cell = table_get_cell (t, c, r);
214 cell->attr.align = a;
218 table_set_cell_fg_color (table_t *t, int c, int r, table_text_attr_color_t v)
220 table_cell_t *cell = table_get_cell (t, c, r);
221 cell->attr.fg_color = v & 0x7;
222 cell->attr.flags |= TTAF_FG_COLOR_SET;
224 cell->attr.flags |= TTAF_FG_COLOR_BRIGHT;
226 cell->attr.flags &= ~TTAF_FG_COLOR_BRIGHT;
230 table_set_cell_bg_color (table_t *t, int c, int r, table_text_attr_color_t v)
232 table_cell_t *cell = table_get_cell (t, c, r);
233 cell->attr.bg_color = v & 0x7;
234 cell->attr.flags |= TTAF_BG_COLOR_SET;
236 cell->attr.flags |= TTAF_BG_COLOR_BRIGHT;
238 cell->attr.flags &= ~TTAF_BG_COLOR_BRIGHT;
242 table_free (table_t *t)
244 for (int c = 0; c < vec_len (t->cells); c++)
246 for (int r = 0; r < vec_len (t->cells[c]); r++)
247 vec_free (t->cells[c][r].text);
248 vec_free (t->cells[c]);
251 vec_free (t->row_sizes);
253 clib_memset (t, 0, sizeof (table_t));
257 table_add_header_col (table_t *t, int n_strings, ...)
260 int r, c = t->n_header_cols++;
263 vec_insert (t->cells, 1, c);
264 n_rows = clib_max (n_strings, 1);
265 n_rows = clib_max (vec_len (t->row_sizes), n_rows);
266 vec_validate (t->cells[c], n_rows - 1);
268 va_start (arg, n_strings);
269 for (r = 0; r < n_rows; r++)
272 table_format_cell (t, -1, r - t->n_header_rows, "%s",
273 va_arg (arg, char *));
279 table_add_header_row (table_t *t, int n_strings, ...)
282 int c, r = t->n_header_rows++;
284 vec_validate (t->cells, n_strings + t->n_header_cols - 1);
286 va_start (arg, n_strings);
287 for (c = t->n_header_cols; c < vec_len (t->cells); c++)
289 vec_insert (t->cells[c + t->n_header_cols], 1, r);
291 table_format_cell (t, c, -1, "%s", va_arg (arg, char *));