4 The table printer module provides formatting of 2-dimensional tables
7 Each table consists of a number of rows, which are processed one
8 after another. All rows have the same number of columns. Internally,
9 the columns have a fixed order, each column has its name and a data
10 type (e.g., int, uint, u64, etc.). The table printer checks that
11 each cell is filled by a value of the appropriate type, except that
12 a string value is allowed in any cell (for example, this allows
13 a numeric cell to be set to "--" or "unknown").
15 Once a table is defined, it can be printed using a variety of formatters
16 (human-readable, tab-separated values, etc.). Also, a subset of columns
17 can be selected and their order changed.
22 Let us construct a simple table of music recordings:
24 First, we define an enum with column indices (the values are automatically
25 numbered starting from 0):
27 // Definition of columns
35 Then we create a structure with the definition of our table.
36 The table columns are defined using the `TBL_COL_xxx` and `TBL_COL_xxx_FMT`
37 macros. Each macro gets the name of the column and its default width
38 in character. The `_FMT` version has an additional argument: the format
39 string for `printf` used for this column. Moreover, various flags can
40 be OR-ed to the width of the column, for example `CELL_ALIGN_LEFT` prescribes
41 that the cell should be aligned to the left.
43 struct table recording_table = {
45 [TBL_REC_ID] = TBL_COL_UINT("id", 16),
46 [TBL_REC_ALBUM_NAME] = TBL_COL_STR_FMT("album-name", 20 | CELL_ALIGN_LEFT, "%s"),
47 [TBL_REC_ARTIST] = TBL_COL_STR("artist", 20),
48 [TBL_REC_YEAR] = TBL_COL_UINT("year", 10),
53 Before you use the table definition, you need to initialize it:
55 table_init(&recording_table);
57 With a single definition, you can print multiple tables. At the start
58 of each table, you should obtain a <<fastbuf:,fastbuf>> where the output
59 should be sent, store it in the table structure and call table_start():
61 struct fastbuf *out = bfdopen_shared(1, 4096);
62 table_start(&recording_table, out);
64 Then you can fill the rows one after another. Each row is ended by
67 table_col_uint(&recording_table, TBL_REC_ID, 0);
68 table_col_str(&recording_table, TBL_REC_ALBUM_NAME, "The Wall");
69 table_col_str(&recording_table, TBL_REC_ARTIST, "Pink Floyd");
70 table_col_uint(&recording_table, TBL_REC_YEAR, 1979);
71 table_end_row(&recording_table);
73 table_col_uint(&recording_table, TBL_REC_ID, 1);
74 table_col_str(&recording_table, TBL_REC_ALBUM_NAME, "Rio Grande Mud");
75 table_col_str(&recording_table, TBL_REC_ARTIST, "ZZ Top");
76 table_col_uint(&recording_table, TBL_REC_YEAR, 1972);
77 table_end_row(&recording_table);
79 Finally, you should close the table by calling table_end():
81 table_end(&recording_table);
83 At this moment, the table structure is ready to be used again. When
84 you do not need it any longer, you can dispose of it by table_cleanup():
86 table_cleanup(&recording_table);