]> mj.ucw.cz Git - libucw.git/blob - ucw/table.h
tableprinter: add of table_clean_row
[libucw.git] / ucw / table.h
1 /*
2  *      UCW Library -- Table printer
3  *
4  *      (c) 2014 Robert Kessl <robert.kessl@economia.cz>
5  */
6
7 #ifndef _UCW_TABLE_H
8 #define _UCW_TABLE_H
9
10 #include <ucw/fastbuf.h>
11 #include <ucw/mempool.h>
12
13 #ifdef CONFIG_UCW_CLEAN_ABI
14 #define table_append_bool ucw_table_append_bool
15 #define table_append_double ucw_table_append_double
16 #define table_append_int ucw_table_append_int
17 #define table_append_intmax ucw_table_append_intmax
18 #define table_append_printf ucw_table_append_printf
19 #define table_append_str ucw_table_append_str
20 #define table_append_u64 ucw_table_append_u64
21 #define table_append_uint ucw_table_append_uint
22 #define table_append_uintmax ucw_table_append_uintmax
23 #define table_cleanup ucw_table_cleanup
24 #define table_col_bool ucw_table_col_bool
25 #define table_col_bool_fmt ucw_table_col_bool_fmt
26 #define table_col_bool_name ucw_table_col_bool_name
27 #define table_col_double ucw_table_col_double
28 #define table_col_fbend ucw_table_col_fbend
29 #define table_col_fbstart ucw_table_col_fbstart
30 #define table_col_int ucw_table_col_int
31 #define table_col_intmax ucw_table_col_intmax
32 #define table_col_printf ucw_table_col_printf
33 #define table_col_str ucw_table_col_str
34 #define table_col_u64 ucw_table_col_u64
35 #define table_col_s64 ucw_table_col_s64
36 #define table_col_uint ucw_table_col_uint
37 #define table_col_uintmax ucw_table_col_uintmax
38 #define table_end ucw_table_end
39 #define table_end_row ucw_table_end_row
40 #define table_fmt_human_readable ucw_table_fmt_human_readable
41 #define table_fmt_machine_readable ucw_table_fmt_machine_readable
42 #define table_get_col_idx ucw_table_get_col_idx
43 #define table_get_col_list ucw_table_get_col_list
44 #define table_init ucw_table_init
45 #define table_set_col_order ucw_table_set_col_order
46 #define table_set_col_order_by_name ucw_table_set_col_order_by_name
47 #define table_set_formatter ucw_table_set_formatter
48 #define table_set_gary_options ucw_table_set_gary_options
49 #define table_set_option ucw_table_set_option
50 #define table_set_option_value ucw_table_set_option_value
51 #define table_start ucw_table_start
52 #endif
53
54 enum column_type {
55   COL_TYPE_STR,
56   COL_TYPE_INT,
57   COL_TYPE_S64,
58   COL_TYPE_INTMAX,
59   COL_TYPE_UINT,
60   COL_TYPE_U64,
61   COL_TYPE_UINTMAX,
62   COL_TYPE_BOOL,
63   COL_TYPE_DOUBLE,
64   COL_TYPE_ANY,
65   COL_TYPE_LAST
66 };
67
68 #define CELL_ALIGN_LEFT     (1<<(sizeof(enum column_type)*8 - 1))
69 // FIXME: an example of another flag, not implemented now
70 #define CELL_ALIGN_CENTER   (1<<(sizeof(enum column_type)*8 - 2))
71 #define CELL_ALIGN_FLOAT    (1<<(sizeof(enum column_type)*8 - 3))
72
73 #define CELL_TRUNC_RIGHT    (1<<(sizeof(enum column_type)*8 - 4))
74
75 // CELL_ALIGN_MASK is a mask which has 1's on positions used by some alignment mask.
76 // that is: col_width & CELL_ALIGN_MASK  gives column width (in characters).
77 // the top bit is reserved for left alignment and is not demasked by CELL_ALIGN_MASK.
78 // the reason is that all printf and friends are using negative number for left alignment.
79 #define CELL_ALIGN_MASK     (~(CELL_ALIGN_LEFT | CELL_ALIGN_FLOAT | CELL_ALIGN_CENTER))
80
81 #define TBL_COL_STR(_name, _width)            { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_STR }
82 #define TBL_COL_INT(_name, _width)            { .name = _name, .width = _width, .fmt = "%d", .type = COL_TYPE_INT }
83 #define TBL_COL_S64(_name, _width)            { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_S64 }
84 #define TBL_COL_UINT(_name, _width)           { .name = _name, .width = _width, .fmt = "%u", .type = COL_TYPE_UINT }
85 #define TBL_COL_U64(_name, _width)            { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_U64 }
86 #define TBL_COL_INTMAX(_name, _width)         { .name = _name, .width = _width, .fmt = "%jd", .type = COL_TYPE_INTMAX }
87 #define TBL_COL_UINTMAX(_name, _width)        { .name = _name, .width = _width, .fmt = "%ju", .type = COL_TYPE_UINTMAX }
88 #define TBL_COL_HEXUINT(_name, _width)        { .name = _name, .width = _width, .fmt = "0x%x", .type = COL_TYPE_UINT }
89 #define TBL_COL_DOUBLE(_name, _width, _prec)  { .name = _name, .width = _width, .fmt = "%." #_prec "lf", .type = COL_TYPE_DOUBLE }
90 #define TBL_COL_BOOL(_name, _width)           { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_BOOL }
91 #define TBL_COL_ANY(_name, _width)            { .name = _name, .width = _width, .fmt = 0, .type = COL_TYPE_ANY }
92
93 #define TBL_COL_STR_FMT(_name, _width, _fmt)            { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_STR }
94 #define TBL_COL_INT_FMT(_name, _width, _fmt)            { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INT }
95 #define TBL_COL_S64_FMT(_name, _width, _fmt)            { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_S64 }
96 #define TBL_COL_UINT_FMT(_name, _width, _fmt)           { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
97 #define TBL_COL_U64_FMT(_name, _width, _fmt)            { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_U64 }
98 #define TBL_COL_INTMAX_FMT(_name, _width, _fmt)         { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INTMAX }
99 #define TBL_COL_UINTMAX_FMT(_name, _width, _fmt)        { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINTMAX }
100 #define TBL_COL_HEXUINT_FMT(_name, _width, _fmt)        { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
101 #define TBL_COL_BOOL_FMT(_name, _width, _fmt)           { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_BOOL }
102
103 #define TBL_COL_END { .name = 0, .width = 0, .fmt = 0, .type = COL_TYPE_LAST }
104
105 #define TBL_COLUMNS  .columns = (struct table_column [])
106 #define TBL_COL_ORDER(order) .column_order = (int *) order, .cols_to_output = ARRAY_SIZE(order)
107 #define TBL_COL_DELIMITER(_delimiter_) .col_delimiter = _delimiter_
108 #define TBL_APPEND_DELIMITER(_delimiter_) .append_delimiter = _delimiter_
109
110 #define TBL_OUTPUT_HUMAN_READABLE     .formatter = &table_fmt_human_readable
111 #define TBL_OUTPUT_BLOCKLINE          .formatter = &table_fmt_blockline
112 #define TBL_OUTPUT_MACHINE_READABLE   .formatter = &table_fmt_machine_readable
113
114 /***
115  * [[ Usage ]]
116  * The table works as follows:
117  * The table can be used after table_init is called. Then at the beginning of each printing, the
118  * table_start function must be called. After printing, the table_end must be called. The
119  * table_start MUST be paired with table_end. Inbetween table_start/table_end the user can set the
120  * cells of one row and one row is finished and printed using table_end_row. The pairs
121  * table_start/table_end can be used multiple-times for one table. The table is deallocated using
122  * table_cleanup. After table_cleanup is called it is not possible to further use the struct table.
123  * The struct table must be reinitialized.
124  *
125  * Default behaviour of the table_col_* is replacement of already set data. To append, the user
126  * must use table_append_*
127  *
128  * To summarize:
129  * 1) @table_init is called;
130  * 2) @table_start is called following by table_col_xxx functions and @table_end.
131  *    table_start/table_end forms 1-level parenthesis structure. Some of the table
132  *    settings can be changed only between table_init and @table_start or after table_end
133  *    is called (but before next table_start.
134  * 3) the table is deallocated using @table_cleanup. After the cleanup
135  *    is done, the struct table is unusable and must be initialized.
136  *
137  *
138  * An example of the procedure is following sequence of calls:
139  *  table_init
140  *
141  *  table_start
142  *  table_end
143  *  table_start
144  *  table_end
145  *
146  *  table_cleanup
147  *
148  * The tableprinter supports user-specified callback for each row and table-print (i.e., a callback
149  * that is called in table_end).
150  *
151  * The table is initialized by defining a table struct using the following macros:
152  *  o TBL_COLUMNS    indicates start of definition of columns
153  *  o TBL_COL_XXX    macros specify the column types with some default formatting the column is specified using a column
154  *                   name (which should be C identifier) and a prefix.  the column name is the a string with the column
155  *                   name. The prefix is used for discriminating between columns from different tables. The column index
156  *                   should be taken from an enum. The enum identifier is prefix concatenated with the column name identifier.
157  *  o TBL_COL_XXX_F  macros specify column types with user supplied formatting
158  *  o TBL_COL_END    indicates end of column definitions
159  *  o TBL_COL_ORDER  specify the column order
160  *  o TBL_COL_DELIMITER specify the in-between cell delimiter
161  *
162  * The table cells have strict type control, with the exception of type TBL_COL_ANY. In the case of
163  * TBL_COL_ANY, the type is not tested and an arbitrary value can be printed into the cell.
164  * It is also possible to print string to an arbitrary cell.
165  *
166  * Features:
167  * - user supplied callback functions can be used for modifying the output format.
168  *
169  * Command-line options (provided through table_set_option and friends):
170  *   key      value                       explanation
171  *  header    [0|1]                       0=do not print the header
172  *  cols      <col-name>[,<col-name>]*    list of column names delimited by comma ','
173  *            '*'                         or star '*' meaning all columns
174  *   fmt      [human|machine|blockline]   output format
175  * col-delim  <string>                    string used as a column delimiter
176  *
177  ***/
178
179 struct table;
180
181 /** Specification of a single table column */
182 struct table_column {
183   const char *name;             // [*] Name of the column displayed in table header
184   int width;                    // [*] Width of the column (in characters). Negative number indicates alignment to left.
185                                 // FIXME: Request left alignment by a flag.
186   const char *fmt;              // [*] Default format of each cell in the column
187   enum column_type type;        // Type of the cells in the column
188 };
189
190 /** The definition of a table. Contains column definitions plus internal data. */
191 struct table {
192   struct table_column *columns;         // [*] Definition of columns
193   int column_count;                     // [*] Number of columns (calculated by table_init())
194   struct mempool *pool;                 // Memory pool used for storing table data. Contains global state
195                                         // and data of the current row.
196   struct mempool_state pool_state;      // State of the pool after the table is initialized, i.e., before
197                                         // per-row data have been allocated.
198
199   char **col_str_ptrs;                  // Values of cells in the current row (allocated from the pool)
200
201   uint *column_order;                   // [*] Order of the columns in the print-out of the table
202   uint cols_to_output;                  // [*] Number of columns that are printed
203   const char *col_delimiter;            // [*] Delimiter that is placed between columns
204   const char *append_delimiter;         // [*] Separator of multiple values in a single cell (see table_append_...())
205   uint print_header;                    // [*] 0 indicates that table header should not be printed
206
207   struct fastbuf *out;                  // [*] Fastbuffer to which the table is printed
208   int last_printed_col;                 // Index of the last column which was set. -1 indicates start of row.
209                                         // Used for example for appending to the current column.
210   int row_printing_started;             // Indicates that a row has been started. Duplicates last_printed_col, but harmlessly.
211   struct fbpool fb_col_out;             // Per-cell fastbuf, see table_col_fbstart()
212   int col_out;                          // Index of the column that is currently printed using fb_col_out
213
214   // Back-end used for table formatting and its private data
215   struct table_formatter *formatter;
216   void *data;
217 };
218
219
220 /**
221  * @table_init serves for initialization of the table. The @tbl parameter should have set the columns member of
222  * the table structure.
223  **/
224 void table_init(struct table *tbl);
225 void table_cleanup(struct table *tbl);
226
227 /**
228  * table_start is called before the cells of the table are set. After the table_start is called, the
229  * user can call the table_col_* or table_append_ functions, but cannot call the table_set_*
230  * functions. The table_end_row function can be called after the table_start is called (but before
231  * the table_end is called)
232  **/
233 void table_start(struct table *tbl, struct fastbuf *out);
234
235 /**
236  * This function must be called after all the rows of the current table are printed. The table_set_*
237  * functions can be called in between table_start and table_end calls.
238  **/
239 void table_end(struct table *tbl);
240
241 /**
242  * Sets the order in which the columns are printed. The @col_order parameter is used until the table_end or
243  * table_cleanup is called. The table stores the pointer only and the memory pointed to by @col_order is
244  * allocated and deallocated by the caller.
245  **/
246 void table_set_col_order(struct table *tbl, int *col_order, int col_order_size);
247
248 /**
249  * Sets the order in which the columns are printed. The specification is a string with comma-separated column
250  * names. Returns NULL for success and an error message otherwise.
251  **/
252 const char *table_set_col_order_by_name(struct table *tbl, const char *col_order);
253
254 /**
255  * Called when all the cells have filled values. The function the prints a table row into the output stream.
256  * The table row has newline at the end.
257  **/
258 void table_end_row(struct table *tbl);
259
260 /**
261  * Cleans current row, When called.
262  **/
263 void table_clean_row(struct table *tbl);
264
265 /**
266  * Prints a string that is printf-like formated into a particular column. This function does not check the
267  * type of the column, i.e., it can be used to print double into an int column
268  **/
269 void table_col_printf(struct table *tbl, int col, const char *fmt, ...) FORMAT_CHECK(printf, 3, 4);
270
271 /**
272  * Appends a string that is printf-like formated to the last printed column. This function does not check the
273  * type of the column, i.e., it can be used to print double into an int column.
274  **/
275 void table_append_printf(struct table *tbl, const char *fmt, ...) FORMAT_CHECK(printf, 2, 3);
276
277 /**
278  * Find the index of a column with name @col_name and returns it. Returns -1 if the column was not found.
279  **/
280 int table_get_col_idx(struct table *tbl, const char *col_name);
281
282 /**
283  * Returns comma-and-space-separated list of column names, allocated from table's internal
284  * memory pool.
285  **/
286 const char *table_get_col_list(struct table *tbl);
287
288 /**
289  * Opens a fastbuf stream that can be used for creating a cell content. The @sz parameter is the initial size
290  * allocated on the memory pool.
291  **/
292 struct fastbuf *table_col_fbstart(struct table *tbl, int col);
293
294 /**
295  * Closes the stream that is used for printing of the last column.
296  **/
297 void table_col_fbend(struct table *tbl);
298
299 /**
300  * Sets table formatter for @tbl.
301  **/
302 void table_set_formatter(struct table *tbl, struct table_formatter *fmt);
303
304 /** Definition of a formatter back-end. **/
305 struct table_formatter {
306   void (*row_output)(struct table *tbl);        // [*] Function that outputs one row
307   void (*table_start)(struct table *tbl);       // [*] table_start callback (optional)
308   void (*table_end)(struct table *tbl);         // [*] table_end callback (optional)
309   bool (*process_option)(struct table *tbl, const char *key, const char *value, const char **err);
310         // [*] Process table option and possibly return an error message (optional)
311 };
312
313 // Standard formatters
314 extern struct table_formatter table_fmt_human_readable;
315 extern struct table_formatter table_fmt_machine_readable;
316 extern struct table_formatter table_fmt_blockline;
317
318 /**
319  * Process the table one option and sets the values in @tbl according to the command-line parameters.
320  * The option has the following format: a) "<key>:<value>"; b) "<key>" (currently not used).
321  *
322  * Possible key-value pairs:
323  * header:[0|1]                     - 1 indicates that the header should be printed, 0 otherwise
324  * noheader                         - equivalent to header:0
325  * cols:<string-with-col-names>     - comma-separated list of columns that will be printed (in the order specified on the cmd-line)
326  * fmt:[human|machine|...]          - output type
327  * col-delim:<char>                 - column delimiter
328  *
329  * Returns NULL on success or an error string otherwise.
330  **/
331 const char *table_set_option(struct table *tbl, const char *opt);
332 const char *table_set_option_value(struct table *tbl, const char *key, const char *value);
333 const char *table_set_gary_options(struct table *tbl, char **gary_table_opts);
334
335 #define TABLE_COL_PROTO(_name_, _type_) void table_col_##_name_(struct table *tbl, int col, _type_ val);\
336   void table_col_##_name_##_name(struct table *tbl, const char *col_name, _type_ val);\
337   void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val) FORMAT_CHECK(printf, 3, 0);
338
339 // table_col_<type>_fmt has one disadvantage: it is not possible to
340 // check whether fmt contains format that contains formatting that is
341 // compatible with _type_
342
343 TABLE_COL_PROTO(int, int);
344 TABLE_COL_PROTO(uint, uint);
345 TABLE_COL_PROTO(double, double);
346 TABLE_COL_PROTO(str, const char *);
347 TABLE_COL_PROTO(intmax, intmax_t);
348 TABLE_COL_PROTO(uintmax, uintmax_t);
349 TABLE_COL_PROTO(s64, s64);
350 TABLE_COL_PROTO(u64, u64);
351
352 void table_col_bool(struct table *tbl, int col, uint val);
353 void table_col_bool_name(struct table *tbl, const char *col_name, uint val);
354 void table_col_bool_fmt(struct table *tbl, int col, const char *fmt, uint val);
355 #undef TABLE_COL_PROTO
356
357 #define TABLE_APPEND_PROTO(_name_, _type_) void table_append_##_name_(struct table *tbl, _type_ val)
358 TABLE_APPEND_PROTO(int, int);
359 TABLE_APPEND_PROTO(uint, uint);
360 TABLE_APPEND_PROTO(double, double);
361 TABLE_APPEND_PROTO(str, const char *);
362 TABLE_APPEND_PROTO(intmax, intmax_t);
363 TABLE_APPEND_PROTO(uintmax, uintmax_t);
364 TABLE_APPEND_PROTO(s64, s64);
365 TABLE_APPEND_PROTO(u64, u64);
366 void table_append_bool(struct table *tbl, int val);
367 #undef TABLE_APPEND_PROTO
368
369 #endif