]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libsmartcols/src/smartcolsP.h
3653eda0704e1fb73390f3f5bdfd62c5589324b4
[thirdparty/util-linux.git] / libsmartcols / src / smartcolsP.h
1 /*
2 * smartcolsP.h - private library header file
3 *
4 * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
5 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
6 *
7 * This file may be redistributed under the terms of the
8 * GNU Lesser General Public License.
9 */
10
11 #ifndef _LIBSMARTCOLS_PRIVATE_H
12 #define _LIBSMARTCOLS_PRIVATE_H
13
14 #include "c.h"
15 #include "list.h"
16 #include "strutils.h"
17 #include "color-names.h"
18 #include "debug.h"
19
20 #include "libsmartcols.h"
21
22 /*
23 * Debug
24 */
25 #define SCOLS_DEBUG_HELP (1 << 0)
26 #define SCOLS_DEBUG_INIT (1 << 1)
27 #define SCOLS_DEBUG_CELL (1 << 2)
28 #define SCOLS_DEBUG_LINE (1 << 3)
29 #define SCOLS_DEBUG_TAB (1 << 4)
30 #define SCOLS_DEBUG_COL (1 << 5)
31 #define SCOLS_DEBUG_BUFF (1 << 6)
32 #define SCOLS_DEBUG_GROUP (1 << 7)
33 #define SCOLS_DEBUG_ALL 0xFFFF
34
35 UL_DEBUG_DECLARE_MASK(libsmartcols);
36 #define DBG(m, x) __UL_DBG(libsmartcols, SCOLS_DEBUG_, m, x)
37 #define ON_DBG(m, x) __UL_DBG_CALL(libsmartcols, SCOLS_DEBUG_, m, x)
38 #define DBG_FLUSH __UL_DBG_FLUSH(libsmartcols, SCOLS_DEBUG_)
39
40 #define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(libsmartcols)
41 #include "debugobj.h"
42
43 /*
44 * Generic iterator
45 */
46 struct libscols_iter {
47 struct list_head *p; /* current position */
48 struct list_head *head; /* start position */
49 int direction; /* SCOLS_ITER_{FOR,BACK}WARD */
50 };
51
52 /*
53 * Tree symbols
54 */
55 struct libscols_symbols {
56 int refcount;
57
58 char *tree_branch;
59 char *tree_vert;
60 char *tree_right;
61
62 char *group_vert;
63 char *group_horz;
64 char *group_first_member;
65 char *group_last_member;
66 char *group_middle_member;
67 char *group_last_child;
68 char *group_middle_child;
69
70 char *title_padding;
71 char *cell_padding;
72 };
73
74 /*
75 * Table cells
76 */
77 struct libscols_cell {
78 char *data;
79 char *color;
80 void *userdata;
81 int flags;
82 };
83
84 extern int scols_line_move_cells(struct libscols_line *ln, size_t newn, size_t oldn);
85
86 /*
87 * Table column
88 */
89 struct libscols_column {
90 int refcount; /* reference counter */
91 size_t seqnum; /* column index */
92
93 size_t width; /* real column width */
94 size_t width_min; /* minimal width (usually header width) */
95 size_t width_max; /* maximal width */
96 size_t width_avg; /* average width, used to detect extreme fields */
97 size_t width_treeart; /* size of the tree ascii art */
98 double width_hint; /* hint (N < 1 is in percent of termwidth) */
99
100 size_t extreme_sum;
101 int extreme_count;
102
103 int json_type; /* SCOLS_JSON_* */
104
105 int flags;
106 char *color; /* default column color */
107 char *safechars; /* do not encode this bytes */
108
109 char *pending_data;
110 size_t pending_data_sz;
111 char *pending_data_buf;
112
113 int (*cmpfunc)(struct libscols_cell *,
114 struct libscols_cell *,
115 void *); /* cells comparison function */
116 void *cmpfunc_data;
117
118 size_t (*wrap_chunksize)(const struct libscols_column *,
119 const char *, void *);
120 char *(*wrap_nextchunk)(const struct libscols_column *,
121 char *, void *);
122 void *wrapfunc_data;
123
124
125 struct libscols_cell header;
126 struct list_head cl_columns;
127
128 struct libscols_table *table;
129
130 unsigned int is_extreme : 1, /* extreme width in the column */
131 is_groups : 1; /* print group chart */
132
133 };
134
135 #define colsep(tb) ((tb)->colsep ? (tb)->colsep : " ")
136 #define linesep(tb) ((tb)->linesep ? (tb)->linesep : "\n")
137
138 enum {
139 SCOLS_GSTATE_NONE = 0, /* not activate yet */
140 SCOLS_GSTATE_FIRST_MEMBER,
141 SCOLS_GSTATE_MIDDLE_MEMBER,
142 SCOLS_GSTATE_LAST_MEMBER,
143 SCOLS_GSTATE_MIDDLE_CHILD,
144 SCOLS_GSTATE_LAST_CHILD,
145 SCOLS_GSTATE_CONT_MEMBERS,
146 SCOLS_GSTATE_CONT_CHILDREN
147 };
148
149 /*
150 * Every group needs at least 3 columns
151 */
152 #define SCOLS_GRPSET_CHUNKSIZ 3
153
154 struct libscols_group {
155 int refcount;
156
157 size_t nmembers;
158
159 struct list_head gr_members; /* head of line->ln_group */
160 struct list_head gr_children; /* head of line->ln_children */
161 struct list_head gr_groups; /* member of table->tb_groups */
162
163 int state; /* SCOLS_GSTATE_* */
164 };
165
166 /*
167 * Table line
168 */
169 struct libscols_line {
170 int refcount;
171 size_t seqnum;
172
173 void *userdata;
174 char *color; /* default line color */
175
176 struct libscols_cell *cells; /* array with data */
177 size_t ncells; /* number of cells */
178
179 struct list_head ln_lines; /* member of table->tb_lines */
180 struct list_head ln_branch; /* head of line->ln_children */
181 struct list_head ln_children; /* member of line->ln_children or group->gr_children */
182 struct list_head ln_groups; /* member of group->gr_groups */
183
184 struct libscols_line *parent;
185 struct libscols_group *parent_group; /* for group childs */
186 struct libscols_group *group; /* for group members */
187 };
188
189 enum {
190 SCOLS_FMT_HUMAN = 0, /* default, human readable */
191 SCOLS_FMT_RAW, /* space separated */
192 SCOLS_FMT_EXPORT, /* COLNAME="data" ... */
193 SCOLS_FMT_JSON /* http://en.wikipedia.org/wiki/JSON */
194 };
195
196 /*
197 * The table
198 */
199 struct libscols_table {
200 int refcount;
201 char *name; /* optional table name (for JSON) */
202 size_t ncols; /* number of columns */
203 size_t ntreecols; /* number of columns with SCOLS_FL_TREE */
204 size_t nlines; /* number of lines */
205 size_t termwidth; /* terminal width (number of columns) */
206 size_t termheight; /* terminal height (number of lines) */
207 size_t termreduce; /* extra blank space */
208 int termforce; /* SCOLS_TERMFORCE_* */
209 FILE *out; /* output stream */
210
211 char *colsep; /* column separator */
212 char *linesep; /* line separator */
213
214 struct list_head tb_columns;
215 struct list_head tb_lines;
216
217 struct list_head tb_groups; /* all defined groups */
218 struct libscols_group **grpset;
219 size_t grpset_size;
220
221 size_t ngrpchlds_pending; /* groups with not yet printed children */
222 struct libscols_line *walk_last_tree_root; /* last root, used by scols_walk_() */
223
224 struct libscols_symbols *symbols;
225 struct libscols_cell title; /* optional table title (for humans) */
226
227 int indent; /* indentation counter */
228 int indent_last_sep;/* last printed has been line separator */
229 int format; /* SCOLS_FMT_* */
230
231 size_t termlines_used; /* printed line counter */
232 size_t header_next; /* where repeat header */
233
234 /* flags */
235 unsigned int ascii :1, /* don't use unicode */
236 colors_wanted :1, /* enable colors */
237 is_term :1, /* isatty() */
238 padding_debug :1, /* output visible padding chars */
239 is_dummy_print :1, /* printing used for width calcualion only */
240 maxout :1, /* maximize output */
241 header_repeat :1, /* print header after libscols_table->termheight */
242 header_printed :1, /* header already printed */
243 priv_symbols :1, /* default private symbols */
244 walk_last_done :1, /* last tree root walked */
245 no_headings :1, /* don't print header */
246 no_encode :1, /* don't care about control and non-printable chars */
247 no_linesep :1, /* don't print line separator */
248 no_wrap :1; /* never wrap lines */
249 };
250
251 #define IS_ITER_FORWARD(_i) ((_i)->direction == SCOLS_ITER_FORWARD)
252 #define IS_ITER_BACKWARD(_i) ((_i)->direction == SCOLS_ITER_BACKWARD)
253
254 #define SCOLS_ITER_INIT(itr, list) \
255 do { \
256 (itr)->p = IS_ITER_FORWARD(itr) ? \
257 (list)->next : (list)->prev; \
258 (itr)->head = (list); \
259 } while(0)
260
261 #define SCOLS_ITER_ITERATE(itr, res, restype, member) \
262 do { \
263 res = list_entry((itr)->p, restype, member); \
264 (itr)->p = IS_ITER_FORWARD(itr) ? \
265 (itr)->p->next : (itr)->p->prev; \
266 } while(0)
267
268
269 static inline int scols_iter_is_last(const struct libscols_iter *itr)
270 {
271 if (!itr || !itr->head || !itr->p)
272 return 0;
273
274 return itr->p == itr->head;
275 }
276
277 /*
278 * line.c
279 */
280 int scols_line_next_group_child(struct libscols_line *ln,
281 struct libscols_iter *itr,
282 struct libscols_line **chld);
283
284
285 /*
286 * table.c
287 */
288 int scols_table_next_group(struct libscols_table *tb,
289 struct libscols_iter *itr,
290 struct libscols_group **gr);
291
292 /*
293 * buffer.c
294 */
295 struct libscols_buffer;
296 extern struct libscols_buffer *new_buffer(size_t sz);
297 extern void free_buffer(struct libscols_buffer *buf);
298 extern int buffer_reset_data(struct libscols_buffer *buf);
299 extern int buffer_append_data(struct libscols_buffer *buf, const char *str);
300 extern int buffer_append_ntimes(struct libscols_buffer *buf, size_t n, const char *str);
301 extern int buffer_set_data(struct libscols_buffer *buf, const char *str);
302 extern void buffer_set_art_index(struct libscols_buffer *buf);
303 extern char *buffer_get_data(struct libscols_buffer *buf);
304 extern size_t buffer_get_size(struct libscols_buffer *buf);
305 extern char *buffer_get_safe_data(struct libscols_table *tb,
306 struct libscols_buffer *buf,
307 size_t *cells,
308 const char *safechars);
309 extern size_t buffer_get_safe_art_size(struct libscols_buffer *buf);
310
311 /*
312 * grouping.c
313 */
314 void scols_ref_group(struct libscols_group *gr);
315 void scols_group_remove_children(struct libscols_group *gr);
316 void scols_group_remove_members(struct libscols_group *gr);
317 void scols_unref_group(struct libscols_group *gr);
318 void scols_groups_fix_members_order(struct libscols_table *tb);
319 int scols_groups_update_grpset(struct libscols_table *tb, struct libscols_line *ln);
320 void scols_groups_reset_state(struct libscols_table *tb);
321 struct libscols_group *scols_grpset_get_printable_children(struct libscols_table *tb);
322
323 /*
324 * walk.c
325 */
326 extern int scols_walk_tree(struct libscols_table *tb,
327 struct libscols_column *cl,
328 int (*callback)(struct libscols_table *,
329 struct libscols_line *,
330 struct libscols_column *,
331 void *),
332 void *data);
333 extern int scols_walk_is_last(struct libscols_table *tb, struct libscols_line *ln);
334
335 /*
336 * calculate.c
337 */
338 extern int __scols_calculate(struct libscols_table *tb, struct libscols_buffer *buf);
339
340 /*
341 * print.c
342 */
343 extern int __cell_to_buffer(struct libscols_table *tb,
344 struct libscols_line *ln,
345 struct libscols_column *cl,
346 struct libscols_buffer *buf);
347
348 void __scols_cleanup_printing(struct libscols_table *tb, struct libscols_buffer *buf);
349 int __scols_initialize_printing(struct libscols_table *tb, struct libscols_buffer **buf);
350 int __scols_print_tree(struct libscols_table *tb, struct libscols_buffer *buf);
351 int __scols_print_table(struct libscols_table *tb, struct libscols_buffer *buf);
352 int __scols_print_header(struct libscols_table *tb, struct libscols_buffer *buf);
353 int __scols_print_title(struct libscols_table *tb);
354 int __scols_print_range(struct libscols_table *tb,
355 struct libscols_buffer *buf,
356 struct libscols_iter *itr,
357 struct libscols_line *end);
358
359 /*
360 * fput.c
361 */
362 extern void fput_indent(struct libscols_table *tb);
363 extern void fput_table_open(struct libscols_table *tb);
364 extern void fput_table_close(struct libscols_table *tb);
365 extern void fput_children_open(struct libscols_table *tb);
366 extern void fput_children_close(struct libscols_table *tb);
367 extern void fput_line_open(struct libscols_table *tb);
368 extern void fput_line_close(struct libscols_table *tb, int last, int last_in_table);
369
370 static inline int is_tree_root(struct libscols_line *ln)
371 {
372 return ln && !ln->parent && !ln->parent_group;
373 }
374
375 static inline int is_last_tree_root(struct libscols_table *tb, struct libscols_line *ln)
376 {
377 if (!ln || !tb || tb->walk_last_tree_root != ln)
378 return 0;
379
380 return 1;
381 }
382
383 static inline int is_child(struct libscols_line *ln)
384 {
385 return ln && ln->parent;
386 }
387
388 static inline int is_last_child(struct libscols_line *ln)
389 {
390 if (!ln || !ln->parent)
391 return 0;
392
393 return list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch);
394 }
395
396 static inline int is_first_child(struct libscols_line *ln)
397 {
398 if (!ln || !ln->parent)
399 return 0;
400
401 return list_entry_is_first(&ln->ln_children, &ln->parent->ln_branch);
402 }
403
404
405 static inline int is_last_column(struct libscols_column *cl)
406 {
407 struct libscols_column *next;
408
409 if (list_entry_is_last(&cl->cl_columns, &cl->table->tb_columns))
410 return 1;
411
412 next = list_entry(cl->cl_columns.next, struct libscols_column, cl_columns);
413 if (next && scols_column_is_hidden(next) && is_last_column(next))
414 return 1;
415 return 0;
416 }
417
418 static inline int is_last_group_member(struct libscols_line *ln)
419 {
420 if (!ln || !ln->group)
421 return 0;
422
423 return list_entry_is_last(&ln->ln_groups, &ln->group->gr_members);
424 }
425
426 static inline int is_first_group_member(struct libscols_line *ln)
427 {
428 if (!ln || !ln->group)
429 return 0;
430
431 return list_entry_is_first(&ln->ln_groups, &ln->group->gr_members);
432 }
433
434 static inline int is_group_member(struct libscols_line *ln)
435 {
436 return ln && ln->group;
437 }
438
439 static inline int is_last_group_child(struct libscols_line *ln)
440 {
441 if (!ln || !ln->parent_group)
442 return 0;
443
444 return list_entry_is_last(&ln->ln_children, &ln->parent_group->gr_children);
445 }
446
447 static inline int is_group_child(struct libscols_line *ln)
448 {
449 return ln && ln->parent_group;
450 }
451
452 static inline int has_groups(struct libscols_table *tb)
453 {
454 return tb && !list_empty(&tb->tb_groups);
455 }
456
457 static inline int has_children(struct libscols_line *ln)
458 {
459 return ln && !list_empty(&ln->ln_branch);
460 }
461
462 static inline int has_group_children(struct libscols_line *ln)
463 {
464 return ln && ln->group && !list_empty(&ln->group->gr_children);
465 }
466
467 #endif /* _LIBSMARTCOLS_PRIVATE_H */