2 * UCW Library -- Table printer
4 * (c) 2014 Robert Kessl <robert.kessl@economia.cz>
10 #include <ucw/fastbuf.h>
11 #include <ucw/mempool.h>
27 #define CELL_ALIGN_LEFT (1<<(sizeof(enum column_type)*8 - 1))
28 // FIXME: an example of another flag, not implemented now
29 #define CELL_ALIGN_CENTER (1<<(sizeof(enum column_type)*8 - 2))
30 #define CELL_ALIGN_FLOAT (1<<(sizeof(enum column_type)*8 - 3))
32 #define CELL_TRUNC_RIGHT (1<<(sizeof(enum column_type)*8 - 4))
34 // CELL_ALIGN_MASK is a mask which has 1's on positions used by some alignment mask.
35 // that is: col_width & CELL_ALIGN_MASK gives column width (in characters).
36 // the top bit is reserved for left alignment and is not demasked by CELL_ALIGN_MASK.
37 // the reason is that all printf and friends are using negative number for left alignment.
38 #define CELL_ALIGN_MASK (~(CELL_ALIGN_LEFT | CELL_ALIGN_FLOAT | CELL_ALIGN_CENTER))
40 #define TBL_COL_STR(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_STR }
41 #define TBL_COL_INT(_name, _width) { .name = _name, .width = _width, .fmt = "%d", .type = COL_TYPE_INT }
42 #define TBL_COL_S64(_name, _width) { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_S64 }
43 #define TBL_COL_UINT(_name, _width) { .name = _name, .width = _width, .fmt = "%u", .type = COL_TYPE_UINT }
44 #define TBL_COL_U64(_name, _width) { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_U64 }
45 #define TBL_COL_INTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%jd", .type = COL_TYPE_INTMAX }
46 #define TBL_COL_UINTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%ju", .type = COL_TYPE_UINTMAX }
47 #define TBL_COL_HEXUINT(_name, _width) { .name = _name, .width = _width, .fmt = "0x%x", .type = COL_TYPE_UINT }
48 #define TBL_COL_DOUBLE(_name, _width, _prec) { .name = _name, .width = _width, .fmt = "%." #_prec "lf", .type = COL_TYPE_DOUBLE }
49 #define TBL_COL_BOOL(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_BOOL }
50 #define TBL_COL_ANY(_name, _width) { .name = _name, .width = _width, .fmt = 0, .type = COL_TYPE_ANY }
52 #define TBL_COL_STR_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_STR }
53 #define TBL_COL_INT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INT }
54 #define TBL_COL_S64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_S64 }
55 #define TBL_COL_UINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
56 #define TBL_COL_U64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_U64 }
57 #define TBL_COL_INTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INTMAX }
58 #define TBL_COL_UINTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINTMAX }
59 #define TBL_COL_HEXUINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
60 #define TBL_COL_BOOL_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_BOOL }
62 #define TBL_COL_END { .name = 0, .width = 0, .fmt = 0, .type = COL_TYPE_LAST }
64 #define TBL_COLUMNS .columns = (struct table_column [])
65 #define TBL_COL_ORDER(order) .column_order = (int *) order, .cols_to_output = ARRAY_SIZE(order)
66 #define TBL_COL_DELIMITER(_delimiter_) .col_delimiter = _delimiter_
67 #define TBL_APPEND_DELIMITER(_delimiter_) .append_delimiter = _delimiter_
69 #define TBL_OUTPUT_HUMAN_READABLE .formatter = &table_fmt_human_readable
70 #define TBL_OUTPUT_MACHINE_READABLE .formatter = &table_fmt_machine_readable
74 * The table works as follows:
75 * The table can be used after table_init is called. Then at the beginning of each printing, the
76 * table_start function must be called. After printing, the table_end must be called. The
77 * table_start MUST be paired with table_end. Inbetween table_start/table_end the user can set the
78 * cells of one row and one row is finished and printed using table_end_row. The pairs
79 * table_start/table_end can be used multiple-times for one table. The table is deallocated using
80 * table_cleanup. After table_cleanup is called it is not possible to further use the struct table.
81 * The struct table must be reinitialized.
83 * Default behaviour of the table_col_* is replacement of already set data. To append, the user
84 * must use table_append_*
87 * 1) @table_init is called;
88 * 2) @table_start is called following by table_col_xxx functions and @table_end.
89 * table_start/table_end forms 1-level parenthesis structure. Some of the table
90 * settings can be changed only between table_init and @table_start or after table_end
91 * is called (but before next table_start.
92 * 3) the table is deallocated using @table_cleanup. After the cleanup
93 * is done, the struct table is unusable and must be initialized.
96 * An example of the procedure is following sequence of calls:
106 * The tableprinter supports user-specified callback for each row and table-print (i.e., a callback
107 * that is called in table_end).
109 * The table is initialized by defining a table struct using the following macros:
110 * o TBL_COLUMNS indicates start of definition of columns
111 * o TBL_COL_XXX macros specify the column types with some default formatting the column is specified using a column
112 * name (which should be C identifier) and a prefix. the column name is the a string with the column
113 * name. The prefix is used for discriminating between columns from different tables. The column index
114 * should be taken from an enum. The enum identifier is prefix concatenated with the column name identifier.
115 * o TBL_COL_XXX_F macros specify column types with user supplied formatting
116 * o TBL_COL_END indicates end of column definitions
117 * o TBL_COL_ORDER specify the column order
118 * o TBL_COL_DELIMITER specify the in-between cell delimiter
120 * The table cells have strict type control, with the exception of type TBL_COL_ANY. In the case of
121 * TBL_COL_ANY, the type is not tested and an arbitrary value can be printed into the cell.
122 * It is also possible to print string to an arbitrary cell.
125 * * user supplied callback functions can be used for modifying the output format.
127 * TODO part/Planned features:
128 * * computing statistics of columns via the table_start_callback/table_end_callback.
129 * * unsupported: (dynamic) alignment of cells which is computed in table_end
131 * TODO: table_set_col_fmt: this functin takes the format string and the value. But I'm not able to
132 * test whether the format string and the type match !!!
134 * TODO: how to print column which is aligned to the left flag for alignment: 1) left; 2) right;
135 * 3) decimal point alignment;
140 /** Specification of a single table column */
141 struct table_column {
142 const char *name; // [*] Name of the column displayed in table header
143 int width; // [*] Width of the column (in characters). Negative number indicates alignment to left.
144 // FIXME: Request left alignment by a flag.
145 const char *fmt; // [*] Default format of each cell in the column
146 enum column_type type; // Type of the cells in the column
149 /** The definition of a table. Contains column definitions plus internal data. */
151 struct table_column *columns; // [*] Definition of columns
152 int column_count; // [*] Number of columns (calculated by table_init())
153 struct mempool *pool; // Memory pool used for storing table data. Contains global state
154 // and data of the current row.
155 struct mempool_state pool_state; // State of the pool after the table is initialized, i.e., before
156 // per-row data have been allocated.
158 char **col_str_ptrs; // Values of cells in the current row (allocated from the pool)
160 uint *column_order; // [*] Order of the columns in the print-out of the table
161 uint cols_to_output; // [*] Number of columns that are printed
162 const char *col_delimiter; // [*] Delimiter that is placed between columns
163 const char *append_delimiter; // [*] Separator of multiple values in a single cell (see table_append_...())
164 uint print_header; // [*] 0 indicates that table header should not be printed
166 struct fastbuf *out; // [*] Fastbuffer to which the table is printed
167 int last_printed_col; // Index of the last column which was set. -1 indicates start of row.
168 // Used for example for appending to the current column.
169 int row_printing_started; // Indicates that a row has been started. Duplicates last_printed_col, but harmlessly.
170 struct fbpool fb_col_out; // Per-cell fastbuf, see table_col_fbstart()
171 int col_out; // Index of the column that is currently printed using fb_col_out
173 // Back-end used for table formatting and its private data
174 struct table_formatter *formatter;
180 * @table_init serves for initialization of the table. The @tbl parameter should have set the columns member of
181 * the table structure.
183 void table_init(struct table *tbl);
184 void table_cleanup(struct table *tbl);
187 * table_start is called before the cells of the table are set. After the table_start is called, the
188 * user can call the table_col_* or table_append_ functions, but cannot call the table_set_*
189 * functions. The table_end_row function can be called after the table_start is called (but before
190 * the table_end is called)
192 void table_start(struct table *tbl, struct fastbuf *out);
195 * This function must be called after all the rows of the current table are printed. The table_set_*
196 * functions can be called in between table_start and table_end calls.
198 void table_end(struct table *tbl);
201 * Sets the order in which the columns are printed. The @col_order parameter is used until the table_end or
202 * table_cleanup is called. The table stores the pointer only and the memory pointed to by @col_order is
203 * allocated and deallocated by the caller.
205 void table_set_col_order(struct table *tbl, int *col_order, int col_order_size);
208 * Sets the order in which the columns are printed. The specification is a string with comma-separated column
209 * names. Returns NULL for success and an error message otherwise.
211 const char *table_set_col_order_by_name(struct table *tbl, const char *col_order);
214 * Called when all the cells have filled values. The function the prints a table row into the output stream.
215 * The table row has newline at the end.
217 void table_end_row(struct table *tbl);
220 * Prints a string that is printf-like formated into a particular column. This function does not check the
221 * type of the column, i.e., it can be used to print double into an int column
223 void table_col_printf(struct table *tbl, int col, const char *fmt, ...) FORMAT_CHECK(printf, 3, 4);
226 * Appends a string that is printf-like formated to the last printed column. This function does not check the
227 * type of the column, i.e., it can be used to print double into an int column.
229 void table_append_printf(struct table *tbl, const char *fmt, ...) FORMAT_CHECK(printf, 2, 3);
232 * Find the index of a column with name @col_name and returns it. Returns -1 if the column was not found.
234 int table_get_col_idx(struct table *tbl, const char *col_name);
237 * Returns comma-and-space-separated list of column names, allocated from table's internal
240 const char *table_get_col_list(struct table *tbl);
243 * Opens a fastbuf stream that can be used for creating a cell content. The @sz parameter is the initial size
244 * allocated on the memory pool.
246 struct fastbuf *table_col_fbstart(struct table *tbl, int col);
249 * Closes the stream that is used for printing of the last column.
251 void table_col_fbend(struct table *tbl);
254 * Sets table formatter for @tbl.
256 void table_set_formatter(struct table *tbl, struct table_formatter *fmt);
258 /** Definition of a formatter back-end. **/
259 struct table_formatter {
260 void (*row_output)(struct table *tbl); // [*] Function that outputs one row
261 void (*table_start)(struct table *tbl); // [*] table_start callback (optional)
262 void (*table_end)(struct table *tbl); // [*] table_end callback (optional)
263 bool (*process_option)(struct table *tbl, const char *key, const char *value, const char **err);
264 // [*] Process table option and possibly return an error message (optional)
267 // Standard formatters
268 extern struct table_formatter table_fmt_human_readable;
269 extern struct table_formatter table_fmt_machine_readable;
272 * Process the table one option and sets the values in @tbl according to the command-line parameters.
273 * The option has the following format: a) "<key>:<value>"; b) "<key>" (currently not used).
275 * Possible key-value pairs:
276 * header:[0|1] - 1 indicates that the header should be printed, 0 otherwise
277 * noheader - equivalent to header:0
278 * cols:<string-with-col-names> - comma-separated list of columns that will be printed (in the order specified on the cmd-line)
279 * fmt:[human|machine|...] - output type
280 * col-delim:<char> - column delimiter
282 * Returns NULL on success or an error string otherwise.
284 const char *table_set_option(struct table *tbl, const char *opt);
285 const char *table_set_option_value(struct table *tbl, const char *key, const char *value);
286 const char *table_set_gary_options(struct table *tbl, char **gary_table_opts);
288 #define TABLE_COL_PROTO(_name_, _type_) void table_col_##_name_(struct table *tbl, int col, _type_ val);\
289 void table_col_##_name_##_name(struct table *tbl, const char *col_name, _type_ val);\
290 void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val) FORMAT_CHECK(printf, 3, 0);
292 // table_col_<type>_fmt has one disadvantage: it is not possible to
293 // check whether fmt contains format that contains formatting that is
294 // compatible with _type_
296 TABLE_COL_PROTO(int, int);
297 TABLE_COL_PROTO(uint, uint);
298 TABLE_COL_PROTO(double, double);
299 TABLE_COL_PROTO(str, const char *);
300 TABLE_COL_PROTO(intmax, intmax_t);
301 TABLE_COL_PROTO(uintmax, uintmax_t);
302 TABLE_COL_PROTO(s64, s64);
303 TABLE_COL_PROTO(u64, u64);
305 void table_col_bool(struct table *tbl, int col, uint val);
306 void table_col_bool_name(struct table *tbl, const char *col_name, uint val);
307 void table_col_bool_fmt(struct table *tbl, int col, const char *fmt, uint val);
308 #undef TABLE_COL_PROTO
310 #define TABLE_APPEND_PROTO(_name_, _type_) void table_append_##_name_(struct table *tbl, _type_ val)
311 TABLE_APPEND_PROTO(int, int);
312 TABLE_APPEND_PROTO(uint, uint);
313 TABLE_APPEND_PROTO(double, double);
314 TABLE_APPEND_PROTO(str, const char *);
315 TABLE_APPEND_PROTO(intmax, intmax_t);
316 TABLE_APPEND_PROTO(uintmax, uintmax_t);
317 TABLE_APPEND_PROTO(s64, s64);
318 TABLE_APPEND_PROTO(u64, u64);
319 void table_append_bool(struct table *tbl, int val);
320 #undef TABLE_APPEND_PROTO