2 * table.c - functions handling the data at the table level
4 * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
5 * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
6 * Copyright (C) 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com>
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
15 * @short_description: container for rows and columns
17 * Table data manipulation API.
29 #include "smartcolsP.h"
32 #define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char | */
33 #define UTF_VR "\342\224\234" /* U+251C, Vertical and right |- */
34 #define UTF_H "\342\224\200" /* U+2500, Horizontal - */
35 #define UTF_UR "\342\224\224" /* U+2514, Up and right '- */
37 #define UTF_V3 "\342\224\206" /* U+2506 Triple Dash Vertical | */
38 #define UTF_H3 "\342\224\210" /* U+2504 Triple Dash Horizontal - */
39 #define UTF_DR "\342\224\214" /* U+250C Down and Right ,- */
40 #define UTF_DH "\342\224\254" /* U+252C Down and Horizontal |' */
42 #define UTF_TR "\342\226\266" /* U+25B6 Black Right-Pointing Triangle > */
43 #endif /* !HAVE_WIDECHAR */
45 #define is_last_column(_tb, _cl) \
46 list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
49 static void check_padding_debug(struct libscols_table
*tb
)
53 assert(libsmartcols_debug_mask
); /* debug has to be enabled! */
55 str
= getenv("LIBSMARTCOLS_DEBUG_PADDING");
56 if (!str
|| (strcmp(str
, "on") != 0 && strcmp(str
, "1") != 0))
59 DBG(INIT
, ul_debugobj(tb
, "padding debug: ENABLE"));
60 tb
->padding_debug
= 1;
66 * Returns: A newly allocated table.
68 struct libscols_table
*scols_new_table(void)
70 struct libscols_table
*tb
;
73 tb
= calloc(1, sizeof(struct libscols_table
));
80 get_terminal_dimension(&c
, &l
);
81 tb
->termwidth
= c
> 0 ? c
: 80;
82 tb
->termheight
= l
> 0 ? l
: 24;
84 INIT_LIST_HEAD(&tb
->tb_lines
);
85 INIT_LIST_HEAD(&tb
->tb_columns
);
86 INIT_LIST_HEAD(&tb
->tb_groups
);
88 DBG(TAB
, ul_debugobj(tb
, "alloc"));
89 ON_DBG(INIT
, check_padding_debug(tb
));
96 * @tb: a pointer to a struct libscols_table instance
98 * Increases the refcount of @tb.
100 void scols_ref_table(struct libscols_table
*tb
)
106 static void scols_table_remove_groups(struct libscols_table
*tb
)
108 while (!list_empty(&tb
->tb_groups
)) {
109 struct libscols_group
*gr
= list_entry(tb
->tb_groups
.next
,
110 struct libscols_group
, gr_groups
);
111 scols_group_remove_children(gr
);
112 scols_group_remove_members(gr
);
113 scols_unref_group(gr
);
119 * @tb: a pointer to a struct libscols_table instance
121 * Decreases the refcount of @tb. When the count falls to zero, the instance
122 * is automatically deallocated.
124 void scols_unref_table(struct libscols_table
*tb
)
126 if (tb
&& (--tb
->refcount
<= 0)) {
127 DBG(TAB
, ul_debugobj(tb
, "dealloc <-"));
128 scols_table_remove_groups(tb
);
129 scols_table_remove_lines(tb
);
130 scols_table_remove_columns(tb
);
131 scols_unref_symbols(tb
->symbols
);
132 scols_reset_cell(&tb
->title
);
138 DBG(TAB
, ul_debug("<- done"));
143 int scols_table_next_group(struct libscols_table
*tb
,
144 struct libscols_iter
*itr
,
145 struct libscols_group
**gr
)
149 if (!tb
|| !itr
|| !gr
)
154 SCOLS_ITER_INIT(itr
, &tb
->tb_groups
);
155 if (itr
->p
!= itr
->head
) {
156 SCOLS_ITER_ITERATE(itr
, *gr
, struct libscols_group
, gr_groups
);
164 * scols_table_set_name:
165 * @tb: a pointer to a struct libscols_table instance
168 * The table name is used for example for JSON top level object name.
170 * Returns: 0, a negative number in case of an error.
174 int scols_table_set_name(struct libscols_table
*tb
, const char *name
)
176 return strdup_to_struct_member(tb
, name
, name
);
180 * scols_table_get_name:
181 * @tb: a pointer to a struct libscols_table instance
183 * Returns: The current name setting of the table @tb
187 const char *scols_table_get_name(const struct libscols_table
*tb
)
193 * scols_table_get_title:
194 * @tb: a pointer to a struct libscols_table instance
196 * The returned pointer is possible to modify by cell functions. Note that
197 * title output alignment on non-tty is hardcoded to 80 output chars. For the
198 * regular terminal it's based on terminal width.
200 * Returns: Title of the table, or NULL in case of blank title.
204 struct libscols_cell
*scols_table_get_title(struct libscols_table
*tb
)
210 * scols_table_add_column:
211 * @tb: a pointer to a struct libscols_table instance
212 * @cl: a pointer to a struct libscols_column instance
214 * Adds @cl to @tb's column list. The column cannot be shared between more
217 * Returns: 0, a negative number in case of an error.
219 int scols_table_add_column(struct libscols_table
*tb
, struct libscols_column
*cl
)
221 struct libscols_iter itr
;
222 struct libscols_line
*ln
;
225 if (!tb
|| !cl
|| cl
->table
)
228 if (!list_empty(&cl
->cl_columns
))
231 if (cl
->flags
& SCOLS_FL_TREE
)
234 DBG(TAB
, ul_debugobj(tb
, "add column"));
235 list_add_tail(&cl
->cl_columns
, &tb
->tb_columns
);
236 cl
->seqnum
= tb
->ncols
++;
238 scols_ref_column(cl
);
240 if (list_empty(&tb
->tb_lines
))
243 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
245 /* Realloc line cell arrays
247 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
248 rc
= scols_line_alloc_cells(ln
, tb
->ncols
);
257 * scols_table_remove_column:
258 * @tb: a pointer to a struct libscols_table instance
259 * @cl: a pointer to a struct libscols_column instance
261 * Removes @cl from @tb.
263 * Returns: 0, a negative number in case of an error.
265 int scols_table_remove_column(struct libscols_table
*tb
,
266 struct libscols_column
*cl
)
268 if (!tb
|| !cl
|| !list_empty(&tb
->tb_lines
))
271 if (cl
->flags
& SCOLS_FL_TREE
)
274 DBG(TAB
, ul_debugobj(tb
, "remove column"));
275 list_del_init(&cl
->cl_columns
);
278 scols_unref_column(cl
);
283 * scols_table_remove_columns:
284 * @tb: a pointer to a struct libscols_table instance
286 * Removes all of @tb's columns.
288 * Returns: 0, a negative number in case of an error.
290 int scols_table_remove_columns(struct libscols_table
*tb
)
292 if (!tb
|| !list_empty(&tb
->tb_lines
))
295 DBG(TAB
, ul_debugobj(tb
, "remove all columns"));
296 while (!list_empty(&tb
->tb_columns
)) {
297 struct libscols_column
*cl
= list_entry(tb
->tb_columns
.next
,
298 struct libscols_column
, cl_columns
);
299 scols_table_remove_column(tb
, cl
);
305 * scols_table_move_column:
307 * @pre: column before the column
308 * @cl: column to move
310 * Move the @cl behind @pre. If the @pre is NULL then the @col is the first
311 * column in the table.
315 * Returns: 0, a negative number in case of an error.
317 int scols_table_move_column(struct libscols_table
*tb
,
318 struct libscols_column
*pre
,
319 struct libscols_column
*cl
)
321 struct list_head
*head
;
322 struct libscols_iter itr
;
323 struct libscols_column
*p
;
324 struct libscols_line
*ln
;
325 size_t n
= 0, oldseq
;
330 if (pre
&& pre
->seqnum
+ 1 == cl
->seqnum
)
332 if (pre
== NULL
&& cl
->seqnum
== 0)
335 DBG(TAB
, ul_debugobj(tb
, "move column %zu behind %zu",
336 cl
->seqnum
, pre
? pre
->seqnum
: 0));
338 list_del_init(&cl
->cl_columns
); /* remove from old position */
340 head
= pre
? &pre
->cl_columns
: &tb
->tb_columns
;
341 list_add(&cl
->cl_columns
, head
); /* add to the new place */
345 /* fix seq. numbers */
346 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
347 while (scols_table_next_column(tb
, &itr
, &p
) == 0)
350 /* move data in lines */
351 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
352 while (scols_table_next_line(tb
, &itr
, &ln
) == 0)
353 scols_line_move_cells(ln
, cl
->seqnum
, oldseq
);
358 * scols_table_new_column:
360 * @name: column header
361 * @whint: column width hint (absolute width: N > 1; relative width: 0 < N < 1)
362 * @flags: flags integer
364 * This is shortcut for
366 * cl = scols_new_column();
367 * scols_column_set_....(cl, ...);
368 * scols_table_add_column(tb, cl);
370 * The column width is possible to define by:
372 * @whint: 0 < N < 1 : relative width, percent of terminal width
374 * @whint: N >= 1 : absolute width, empty column will be truncated to
375 * the column header width if no specified STRICTWIDTH flag
377 * Note that if table has disabled "maxout" flag (disabled by default) than
378 * relative width is used as a hint only. It's possible that column will be
379 * narrow if the specified size is too large for column data.
382 * If the width of all columns is greater than terminal width then library
383 * tries to reduce width of the individual columns. It's done in three stages:
385 * #1 reduce columns with SCOLS_FL_TRUNC flag and with relative width if the
386 * width is greater than width defined by @whint (@whint * terminal_width)
388 * #2 reduce all columns with SCOLS_FL_TRUNC flag
390 * #3 reduce all columns with relative width
392 * The next stage is always used if the previous stage is unsuccessful. Note
393 * that SCOLS_FL_WRAP is interpreted as SCOLS_FL_TRUNC when calculate column
394 * width (if custom wrap function is not specified), but the final text is not
395 * truncated, but wrapped to multi-line cell.
398 * The column is necessary to address by sequential number. The first defined
399 * column has the colnum = 0. For example:
401 * scols_table_new_column(tab, "FOO", 0.5, 0); // colnum = 0
402 * scols_table_new_column(tab, "BAR", 0.5, 0); // colnum = 1
405 * scols_line_get_cell(line, 0); // FOO column
406 * scols_line_get_cell(line, 1); // BAR column
408 * Returns: newly allocated column
410 struct libscols_column
*scols_table_new_column(struct libscols_table
*tb
,
415 struct libscols_column
*cl
;
416 struct libscols_cell
*hr
;
421 DBG(TAB
, ul_debugobj(tb
, "new column name=%s, whint=%g, flags=%d",
422 name
, whint
, flags
));
423 cl
= scols_new_column();
427 /* set column name */
428 hr
= scols_column_get_header(cl
);
431 if (scols_cell_set_data(hr
, name
))
434 scols_column_set_whint(cl
, whint
);
435 scols_column_set_flags(cl
, flags
);
437 if (scols_table_add_column(tb
, cl
)) /* this increments column ref-counter */
440 scols_unref_column(cl
);
443 scols_unref_column(cl
);
448 * scols_table_next_column:
449 * @tb: a pointer to a struct libscols_table instance
450 * @itr: a pointer to a struct libscols_iter instance
451 * @cl: a pointer to a pointer to a struct libscols_column instance
453 * Returns the next column of @tb via @cl.
455 * Returns: 0, a negative value in case of an error.
457 int scols_table_next_column(struct libscols_table
*tb
,
458 struct libscols_iter
*itr
,
459 struct libscols_column
**cl
)
463 if (!tb
|| !itr
|| !cl
)
468 SCOLS_ITER_INIT(itr
, &tb
->tb_columns
);
469 if (itr
->p
!= itr
->head
) {
470 SCOLS_ITER_ITERATE(itr
, *cl
, struct libscols_column
, cl_columns
);
478 * scols_table_set_columns_iter:
483 * Sets @iter to the position of @cl in the file @tb.
485 * Returns: 0 on success, negative number in case of error.
487 int scols_table_set_columns_iter(
488 struct libscols_table
*tb
,
489 struct libscols_iter
*itr
,
490 struct libscols_column
*cl
)
492 if (!tb
|| !itr
|| !cl
)
498 SCOLS_ITER_INIT(itr
, &tb
->tb_columns
);
499 itr
->p
= &cl
->cl_columns
;
505 * scols_table_get_ncols:
508 * Returns: the ncols table member.
510 size_t scols_table_get_ncols(const struct libscols_table
*tb
)
516 * scols_table_get_nlines:
519 * Returns: the nlines table member.
521 size_t scols_table_get_nlines(const struct libscols_table
*tb
)
527 * scols_table_set_stream:
529 * @stream: output stream
531 * Sets the output stream for table @tb.
533 * Returns: 0, a negative number in case of an error.
535 int scols_table_set_stream(struct libscols_table
*tb
, FILE *stream
)
541 DBG(TAB
, ul_debugobj(tb
, "setting alternative stream"));
547 * scols_table_get_stream:
550 * Gets the output stream for table @tb.
552 * Returns: stream pointer, NULL in case of an error or an unset stream.
554 FILE *scols_table_get_stream(const struct libscols_table
*tb
)
560 * scols_table_reduce_termwidth:
564 * If necessary then libsmartcols use all terminal width, the @reduce setting
565 * provides extra space (for example for borders in ncurses applications).
567 * The @reduce must be smaller than terminal width, otherwise it's silently
568 * ignored. The reduction is not applied when STDOUT_FILENO is not terminal.
570 * Note that after output initialization (scols_table_print_* calls) the width
571 * will be reduced, this behavior affects subsequenced scols_table_get_termwidth()
574 * Returns: 0, a negative value in case of an error.
576 int scols_table_reduce_termwidth(struct libscols_table
*tb
, size_t reduce
)
581 DBG(TAB
, ul_debugobj(tb
, "reduce terminal width: %zu", reduce
));
582 tb
->termreduce
= reduce
;
587 * scols_table_get_column:
589 * @n: number of column (0..N)
591 * Returns: pointer to column or NULL
593 struct libscols_column
*scols_table_get_column(struct libscols_table
*tb
,
596 struct libscols_iter itr
;
597 struct libscols_column
*cl
;
604 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
605 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
613 * scols_table_add_line:
617 * Note that this function calls scols_line_alloc_cells() if number
618 * of the cells in the line is too small for @tb.
620 * Returns: 0, a negative value in case of an error.
622 int scols_table_add_line(struct libscols_table
*tb
, struct libscols_line
*ln
)
627 if (!list_empty(&ln
->ln_lines
))
630 if (tb
->ncols
> ln
->ncells
) {
631 int rc
= scols_line_alloc_cells(ln
, tb
->ncols
);
636 DBG(TAB
, ul_debugobj(tb
, "add line"));
637 list_add_tail(&ln
->ln_lines
, &tb
->tb_lines
);
638 ln
->seqnum
= tb
->nlines
++;
644 * scols_table_remove_line:
648 * Note that this function does not destroy the parent<->child relationship between lines.
649 * You have to call scols_line_remove_child()
651 * Returns: 0, a negative value in case of an error.
653 int scols_table_remove_line(struct libscols_table
*tb
,
654 struct libscols_line
*ln
)
659 DBG(TAB
, ul_debugobj(tb
, "remove line"));
660 list_del_init(&ln
->ln_lines
);
662 scols_unref_line(ln
);
667 * scols_table_remove_lines:
670 * This empties the table and also destroys all the parent<->child relationships.
672 void scols_table_remove_lines(struct libscols_table
*tb
)
677 DBG(TAB
, ul_debugobj(tb
, "remove all lines"));
678 while (!list_empty(&tb
->tb_lines
)) {
679 struct libscols_line
*ln
= list_entry(tb
->tb_lines
.next
,
680 struct libscols_line
, ln_lines
);
682 scols_line_remove_child(ln
->parent
, ln
);
683 scols_table_remove_line(tb
, ln
);
688 * scols_table_next_line:
689 * @tb: a pointer to a struct libscols_table instance
690 * @itr: a pointer to a struct libscols_iter instance
691 * @ln: a pointer to a pointer to a struct libscols_line instance
693 * Finds the next line and returns a pointer to it via @ln.
695 * Returns: 0, a negative value in case of an error.
697 int scols_table_next_line(struct libscols_table
*tb
,
698 struct libscols_iter
*itr
,
699 struct libscols_line
**ln
)
703 if (!tb
|| !itr
|| !ln
)
708 SCOLS_ITER_INIT(itr
, &tb
->tb_lines
);
709 if (itr
->p
!= itr
->head
) {
710 SCOLS_ITER_ITERATE(itr
, *ln
, struct libscols_line
, ln_lines
);
718 * scols_table_new_line:
720 * @parent: parental line or NULL
722 * This is shortcut for
724 * ln = scols_new_line();
725 * scols_table_add_line(tb, ln);
726 * scols_line_add_child(parent, ln);
729 * Returns: newly allocate line
731 struct libscols_line
*scols_table_new_line(struct libscols_table
*tb
,
732 struct libscols_line
*parent
)
734 struct libscols_line
*ln
;
739 ln
= scols_new_line();
743 if (scols_table_add_line(tb
, ln
))
746 scols_line_add_child(parent
, ln
);
748 scols_unref_line(ln
); /* ref-counter incremented by scols_table_add_line() */
751 scols_unref_line(ln
);
756 * scols_table_get_line:
758 * @n: column number (0..N)
760 * Returns: a line or NULL
762 struct libscols_line
*scols_table_get_line(struct libscols_table
*tb
,
765 struct libscols_iter itr
;
766 struct libscols_line
*ln
;
773 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
774 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
785 * Creates a new independent table copy, except struct libscols_symbols that
786 * are shared between the tables.
788 * Returns: a newly allocated copy of @tb
790 struct libscols_table
*scols_copy_table(struct libscols_table
*tb
)
792 struct libscols_table
*ret
;
793 struct libscols_line
*ln
;
794 struct libscols_column
*cl
;
795 struct libscols_iter itr
;
799 ret
= scols_new_table();
803 DBG(TAB
, ul_debugobj(tb
, "copy"));
806 scols_table_set_symbols(ret
, tb
->symbols
);
809 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
810 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
811 cl
= scols_copy_column(cl
);
814 if (scols_table_add_column(ret
, cl
))
816 scols_unref_column(cl
);
820 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
821 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
822 struct libscols_line
*newln
= scols_copy_line(ln
);
825 if (scols_table_add_line(ret
, newln
))
828 struct libscols_line
*p
=
829 scols_table_get_line(ret
, ln
->parent
->seqnum
);
831 scols_line_add_child(p
, newln
);
833 scols_unref_line(newln
);
837 if (scols_table_set_column_separator(ret
, tb
->colsep
) ||
838 scols_table_set_line_separator(ret
, tb
->linesep
))
843 scols_unref_table(ret
);
848 * scols_table_set_default_symbols:
851 * The library check the current environment to select ASCII or UTF8 symbols.
852 * This default behavior could be controlled by scols_table_enable_ascii().
854 * Use scols_table_set_symbols() to unset symbols or use your own setting.
856 * Returns: 0, a negative value in case of an error.
860 int scols_table_set_default_symbols(struct libscols_table
*tb
)
862 struct libscols_symbols
*sy
;
868 DBG(TAB
, ul_debugobj(tb
, "setting default symbols"));
870 sy
= scols_new_symbols();
874 #if defined(HAVE_WIDECHAR)
875 if (!scols_table_is_ascii(tb
) &&
876 !strcmp(nl_langinfo(CODESET
), "UTF-8")) {
878 scols_symbols_set_branch(sy
, UTF_VR UTF_H
);
879 scols_symbols_set_vertical(sy
, UTF_V
" ");
880 scols_symbols_set_right(sy
, UTF_UR UTF_H
);
882 scols_symbols_set_group_horizontal(sy
, UTF_H3
);
883 scols_symbols_set_group_vertical(sy
, UTF_V3
);
885 scols_symbols_set_group_first_member(sy
, UTF_DR UTF_H3 UTF_TR
);
886 scols_symbols_set_group_last_member(sy
, UTF_UR UTF_DH UTF_TR
);
887 scols_symbols_set_group_middle_member(sy
, UTF_VR UTF_H3 UTF_TR
);
888 scols_symbols_set_group_last_child(sy
, UTF_UR UTF_H3
);
889 scols_symbols_set_group_middle_child(sy
, UTF_VR UTF_H3
);
894 scols_symbols_set_branch(sy
, "|-");
895 scols_symbols_set_vertical(sy
, "| ");
896 scols_symbols_set_right(sy
, "`-");
898 scols_symbols_set_group_horizontal(sy
, "-");
899 scols_symbols_set_group_vertical(sy
, "|");
901 scols_symbols_set_group_first_member(sy
, ",->");
902 scols_symbols_set_group_last_member(sy
, "'->");
903 scols_symbols_set_group_middle_member(sy
, "|->");
904 scols_symbols_set_group_last_child(sy
, "`-");
905 scols_symbols_set_group_middle_child(sy
, "|-");
907 scols_symbols_set_title_padding(sy
, " ");
908 scols_symbols_set_cell_padding(sy
, " ");
910 rc
= scols_table_set_symbols(tb
, sy
);
911 scols_unref_symbols(sy
);
917 * scols_table_set_symbols:
919 * @sy: symbols or NULL
921 * Add a reference to @sy from the table. The symbols are used by library to
922 * draw tree output. If no symbols are used for the table then library creates
923 * default temporary symbols to draw output by scols_table_set_default_symbols().
925 * If @sy is NULL then remove reference from the currently used symbols.
927 * Returns: 0, a negative value in case of an error.
929 int scols_table_set_symbols(struct libscols_table
*tb
,
930 struct libscols_symbols
*sy
)
937 DBG(TAB
, ul_debugobj(tb
, "remove symbols reference"));
938 scols_unref_symbols(tb
->symbols
);
943 if (sy
) { /* ref user defined */
944 DBG(TAB
, ul_debugobj(tb
, "set symbols"));
946 scols_ref_symbols(sy
);
952 * scols_table_get_symbols:
955 * Returns: pointer to symbols table.
959 struct libscols_symbols
*scols_table_get_symbols(const struct libscols_table
*tb
)
965 * scols_table_enable_nolinesep:
969 * Enable/disable line separator printing. This is useful if you want to
970 * re-printing the same line more than once (e.g. progress bar). Don't use it
971 * if you're not sure.
973 * Note that for the last line in the table the separator is disabled at all.
974 * The library differentiate between table terminator and line terminator
975 * (although for standard output \n byte is used in both cases).
977 * Returns: 0 on success, negative number in case of an error.
979 int scols_table_enable_nolinesep(struct libscols_table
*tb
, int enable
)
984 DBG(TAB
, ul_debugobj(tb
, "nolinesep: %s", enable
? "ENABLE" : "DISABLE"));
985 tb
->no_linesep
= enable
? 1 : 0;
990 * scols_table_is_nolinesep:
991 * @tb: a pointer to a struct libscols_table instance
993 * Returns: 1 if line separator printing is disabled.
997 int scols_table_is_nolinesep(const struct libscols_table
*tb
)
999 return tb
->no_linesep
;
1003 * scols_table_enable_colors:
1007 * Enable/disable colors.
1009 * Returns: 0 on success, negative number in case of an error.
1011 int scols_table_enable_colors(struct libscols_table
*tb
, int enable
)
1016 DBG(TAB
, ul_debugobj(tb
, "colors: %s", enable
? "ENABLE" : "DISABLE"));
1017 tb
->colors_wanted
= enable
;
1022 * scols_table_enable_raw:
1026 * Enable/disable raw output format. The parsable output formats
1027 * (export, raw, JSON, ...) are mutually exclusive.
1029 * Returns: 0 on success, negative number in case of an error.
1031 int scols_table_enable_raw(struct libscols_table
*tb
, int enable
)
1036 DBG(TAB
, ul_debugobj(tb
, "raw: %s", enable
? "ENABLE" : "DISABLE"));
1038 tb
->format
= SCOLS_FMT_RAW
;
1039 else if (tb
->format
== SCOLS_FMT_RAW
)
1045 * scols_table_enable_json:
1049 * Enable/disable JSON output format. The parsable output formats
1050 * (export, raw, JSON, ...) are mutually exclusive.
1052 * Returns: 0 on success, negative number in case of an error.
1056 int scols_table_enable_json(struct libscols_table
*tb
, int enable
)
1061 DBG(TAB
, ul_debugobj(tb
, "json: %s", enable
? "ENABLE" : "DISABLE"));
1063 tb
->format
= SCOLS_FMT_JSON
;
1064 else if (tb
->format
== SCOLS_FMT_JSON
)
1070 * scols_table_enable_export:
1074 * Enable/disable export output format (COLUMNAME="value" ...).
1075 * The parsable output formats (export and raw) are mutually exclusive.
1077 * Returns: 0 on success, negative number in case of an error.
1079 int scols_table_enable_export(struct libscols_table
*tb
, int enable
)
1084 DBG(TAB
, ul_debugobj(tb
, "export: %s", enable
? "ENABLE" : "DISABLE"));
1086 tb
->format
= SCOLS_FMT_EXPORT
;
1087 else if (tb
->format
== SCOLS_FMT_EXPORT
)
1093 * scols_table_enable_ascii:
1097 * The ASCII-only output is relevant for tree-like outputs. The library
1098 * checks if the current environment is UTF8 compatible by default. This
1099 * function overrides this check and force the library to use ASCII chars
1102 * If a custom libcols_symbols are specified (see scols_table_set_symbols()
1103 * then ASCII flag setting is ignored.
1105 * Returns: 0 on success, negative number in case of an error.
1107 int scols_table_enable_ascii(struct libscols_table
*tb
, int enable
)
1112 DBG(TAB
, ul_debugobj(tb
, "ascii: %s", enable
? "ENABLE" : "DISABLE"));
1113 tb
->ascii
= enable
? 1 : 0;
1118 * scols_table_enable_noheadings:
1122 * Enable/disable header line.
1124 * Returns: 0 on success, negative number in case of an error.
1126 int scols_table_enable_noheadings(struct libscols_table
*tb
, int enable
)
1130 DBG(TAB
, ul_debugobj(tb
, "noheading: %s", enable
? "ENABLE" : "DISABLE"));
1131 tb
->no_headings
= enable
? 1 : 0;
1136 * scols_table_enable_header_repeat:
1140 * Enable/disable header line repeat. The header line is printed only once by
1141 * default. Note that the flag will be silently ignored and disabled if the
1142 * output is not on terminal or output format is JSON, raw, etc.
1144 * Returns: 0 on success, negative number in case of an error.
1148 int scols_table_enable_header_repeat(struct libscols_table
*tb
, int enable
)
1152 DBG(TAB
, ul_debugobj(tb
, "header-repeat: %s", enable
? "ENABLE" : "DISABLE"));
1153 tb
->header_repeat
= enable
? 1 : 0;
1158 * scols_table_enable_maxout:
1162 * The extra space after last column is ignored by default. The output
1163 * maximization add padding for all columns.
1165 * This setting is mutually exclusive to cols_table_enable_minout().
1167 * Returns: 0 on success, negative number in case of an error.
1169 int scols_table_enable_maxout(struct libscols_table
*tb
, int enable
)
1171 if (!tb
|| tb
->minout
)
1174 DBG(TAB
, ul_debugobj(tb
, "maxout: %s", enable
? "ENABLE" : "DISABLE"));
1175 tb
->maxout
= enable
? 1 : 0;
1180 * scols_table_enable_minout:
1184 * Force library to terminate line after last column with data. The extra
1185 * padding is not added to the empty cells at the end of the line. The default is fill
1186 * tailing empty cells except the last line cell.
1188 * This setting is mutually exclusive to cols_table_enable_maxout().
1190 * Returns: 0 on success, negative number in case of an error.
1192 int scols_table_enable_minout(struct libscols_table
*tb
, int enable
)
1194 if (!tb
|| tb
->maxout
)
1197 DBG(TAB
, ul_debugobj(tb
, "minout: %s", enable
? "ENABLE" : "DISABLE"));
1198 tb
->minout
= enable
? 1 : 0;
1203 * scols_table_enable_nowrap:
1207 * Never continue on next line, remove last column(s) when too large, truncate last column.
1209 * Returns: 0 on success, negative number in case of an error.
1213 int scols_table_enable_nowrap(struct libscols_table
*tb
, int enable
)
1217 DBG(TAB
, ul_debugobj(tb
, "nowrap: %s", enable
? "ENABLE" : "DISABLE"));
1218 tb
->no_wrap
= enable
? 1 : 0;
1223 * scols_table_is_nowrap:
1224 * @tb: a pointer to a struct libscols_table instance
1226 * Returns: 1 if nowrap is enabled.
1230 int scols_table_is_nowrap(const struct libscols_table
*tb
)
1236 * scols_table_enable_noencoding:
1240 * The library encode non-printable and control chars by \xHEX by default.
1242 * Returns: 0 on success, negative number in case of an error.
1246 int scols_table_enable_noencoding(struct libscols_table
*tb
, int enable
)
1250 DBG(TAB
, ul_debugobj(tb
, "encoding: %s", enable
? "ENABLE" : "DISABLE"));
1251 tb
->no_encode
= enable
? 1 : 0;
1256 * scols_table_is_noencoding:
1257 * @tb: a pointer to a struct libscols_table instance
1259 * Returns: 1 if encoding is disabled.
1263 int scols_table_is_noencoding(const struct libscols_table
*tb
)
1265 return tb
->no_encode
;
1269 * scols_table_colors_wanted:
1272 * Returns: 1 if colors are enabled.
1274 int scols_table_colors_wanted(const struct libscols_table
*tb
)
1276 return tb
->colors_wanted
;
1280 * scols_table_is_empty:
1283 * Returns: 1 if the table is empty.
1285 int scols_table_is_empty(const struct libscols_table
*tb
)
1291 * scols_table_is_ascii:
1294 * Returns: 1 if ASCII tree is enabled.
1296 int scols_table_is_ascii(const struct libscols_table
*tb
)
1302 * scols_table_is_noheadings:
1305 * Returns: 1 if header output is disabled.
1307 int scols_table_is_noheadings(const struct libscols_table
*tb
)
1309 return tb
->no_headings
;
1313 * scols_table_is_header_repeat
1316 * Returns: 1 if header repeat is enabled.
1320 int scols_table_is_header_repeat(const struct libscols_table
*tb
)
1322 return tb
->header_repeat
;
1326 * scols_table_is_export:
1329 * Returns: 1 if export output format is enabled.
1331 int scols_table_is_export(const struct libscols_table
*tb
)
1333 return tb
->format
== SCOLS_FMT_EXPORT
;
1337 * scols_table_is_raw:
1340 * Returns: 1 if raw output format is enabled.
1342 int scols_table_is_raw(const struct libscols_table
*tb
)
1344 return tb
->format
== SCOLS_FMT_RAW
;
1348 * scols_table_is_json:
1351 * Returns: 1 if JSON output format is enabled.
1355 int scols_table_is_json(const struct libscols_table
*tb
)
1357 return tb
->format
== SCOLS_FMT_JSON
;
1361 * scols_table_is_maxout
1364 * Returns: 1 if output maximization is enabled or 0
1366 int scols_table_is_maxout(const struct libscols_table
*tb
)
1372 * scols_table_is_minout
1375 * Returns: 1 if output minimization is enabled or 0
1377 int scols_table_is_minout(const struct libscols_table
*tb
)
1383 * scols_table_is_tree:
1386 * Returns: returns 1 tree-like output is expected.
1388 int scols_table_is_tree(const struct libscols_table
*tb
)
1390 return tb
->ntreecols
> 0;
1394 * scols_table_set_column_separator:
1398 * Sets the column separator of @tb to @sep.
1400 * Returns: 0, a negative value in case of an error.
1402 int scols_table_set_column_separator(struct libscols_table
*tb
, const char *sep
)
1404 return strdup_to_struct_member(tb
, colsep
, sep
);
1408 * scols_table_set_line_separator:
1412 * Sets the line separator of @tb to @sep.
1414 * Returns: 0, a negative value in case of an error.
1416 int scols_table_set_line_separator(struct libscols_table
*tb
, const char *sep
)
1418 return strdup_to_struct_member(tb
, linesep
, sep
);
1422 * scols_table_get_column_separator:
1425 * Returns: @tb column separator, NULL in case of an error
1427 const char *scols_table_get_column_separator(const struct libscols_table
*tb
)
1433 * scols_table_get_line_separator:
1436 * Returns: @tb line separator, NULL in case of an error
1438 const char *scols_table_get_line_separator(const struct libscols_table
*tb
)
1442 /* for lines in the struct libscols_line->ln_lines list */
1443 static int cells_cmp_wrapper_lines(struct list_head
*a
, struct list_head
*b
, void *data
)
1445 struct libscols_column
*cl
= (struct libscols_column
*) data
;
1446 struct libscols_line
*ra
, *rb
;
1447 struct libscols_cell
*ca
, *cb
;
1453 ra
= list_entry(a
, struct libscols_line
, ln_lines
);
1454 rb
= list_entry(b
, struct libscols_line
, ln_lines
);
1455 ca
= scols_line_get_cell(ra
, cl
->seqnum
);
1456 cb
= scols_line_get_cell(rb
, cl
->seqnum
);
1458 return cl
->cmpfunc(ca
, cb
, cl
->cmpfunc_data
);
1461 /* for lines in the struct libscols_line->ln_children list */
1462 static int cells_cmp_wrapper_children(struct list_head
*a
, struct list_head
*b
, void *data
)
1464 struct libscols_column
*cl
= (struct libscols_column
*) data
;
1465 struct libscols_line
*ra
, *rb
;
1466 struct libscols_cell
*ca
, *cb
;
1472 ra
= list_entry(a
, struct libscols_line
, ln_children
);
1473 rb
= list_entry(b
, struct libscols_line
, ln_children
);
1474 ca
= scols_line_get_cell(ra
, cl
->seqnum
);
1475 cb
= scols_line_get_cell(rb
, cl
->seqnum
);
1477 return cl
->cmpfunc(ca
, cb
, cl
->cmpfunc_data
);
1481 static int sort_line_children(struct libscols_line
*ln
, struct libscols_column
*cl
)
1483 struct list_head
*p
;
1485 if (!list_empty(&ln
->ln_branch
)) {
1486 list_for_each(p
, &ln
->ln_branch
) {
1487 struct libscols_line
*chld
=
1488 list_entry(p
, struct libscols_line
, ln_children
);
1489 sort_line_children(chld
, cl
);
1492 list_sort(&ln
->ln_branch
, cells_cmp_wrapper_children
, cl
);
1495 if (is_first_group_member(ln
)) {
1496 list_for_each(p
, &ln
->group
->gr_children
) {
1497 struct libscols_line
*chld
=
1498 list_entry(p
, struct libscols_line
, ln_children
);
1499 sort_line_children(chld
, cl
);
1502 list_sort(&ln
->group
->gr_children
, cells_cmp_wrapper_children
, cl
);
1511 * @cl: order by this column
1513 * Orders the table by the column. See also scols_column_set_cmpfunc(). If the
1514 * tree output is enabled then children in the tree are recursively sorted too.
1516 * Returns: 0, a negative value in case of an error.
1518 int scols_sort_table(struct libscols_table
*tb
, struct libscols_column
*cl
)
1520 if (!tb
|| !cl
|| !cl
->cmpfunc
)
1523 DBG(TAB
, ul_debugobj(tb
, "sorting table"));
1524 list_sort(&tb
->tb_lines
, cells_cmp_wrapper_lines
, cl
);
1526 if (scols_table_is_tree(tb
)) {
1527 struct libscols_line
*ln
;
1528 struct libscols_iter itr
;
1530 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
1531 while (scols_table_next_line(tb
, &itr
, &ln
) == 0)
1532 sort_line_children(ln
, cl
);
1538 static struct libscols_line
*move_line_and_children(struct libscols_line
*ln
, struct libscols_line
*pre
)
1541 list_del_init(&ln
->ln_lines
); /* remove from old position */
1542 list_add(&ln
->ln_lines
, &pre
->ln_lines
); /* add to the new place (behind @pre) */
1546 if (!list_empty(&ln
->ln_branch
)) {
1547 struct list_head
*p
;
1549 list_for_each(p
, &ln
->ln_branch
) {
1550 struct libscols_line
*chld
=
1551 list_entry(p
, struct libscols_line
, ln_children
);
1552 pre
= move_line_and_children(chld
, pre
);
1560 * scols_sort_table_by_tree:
1563 * Reorders lines in the table by parent->child relation. Note that order of
1564 * the lines in the table is independent on the tree hierarchy.
1568 * Returns: 0, a negative value in case of an error.
1570 int scols_sort_table_by_tree(struct libscols_table
*tb
)
1572 struct libscols_line
*ln
;
1573 struct libscols_iter itr
;
1578 DBG(TAB
, ul_debugobj(tb
, "sorting table by tree"));
1580 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
1581 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
1585 move_line_and_children(ln
, NULL
);
1593 * scols_table_set_termforce:
1595 * @force: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO}
1597 * Forces library to use stdout as terminal, non-terminal or use automatic
1598 * detection (default).
1600 * Returns: 0, a negative value in case of an error.
1604 int scols_table_set_termforce(struct libscols_table
*tb
, int force
)
1608 tb
->termforce
= force
;
1613 * scols_table_get_termforce:
1616 * Returns: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO} or a negative value in case of an error.
1620 int scols_table_get_termforce(const struct libscols_table
*tb
)
1622 return tb
->termforce
;
1626 * scols_table_set_termwidth
1628 * @width: terminal width
1630 * The library automatically detects terminal width or defaults to 80 chars if
1631 * detections is unsuccessful. This function override this behaviour.
1633 * Returns: 0, a negative value in case of an error.
1637 int scols_table_set_termwidth(struct libscols_table
*tb
, size_t width
)
1639 DBG(TAB
, ul_debugobj(tb
, "set terminatl width: %zu", width
));
1640 tb
->termwidth
= width
;
1645 * scols_table_get_termwidth
1648 * Returns: terminal width.
1650 size_t scols_table_get_termwidth(const struct libscols_table
*tb
)
1652 return tb
->termwidth
;
1656 * scols_table_set_termheight
1658 * @height: terminal height (number of lines)
1660 * The library automatically detects terminal height or defaults to 24 lines if
1661 * detections is unsuccessful. This function override this behaviour.
1663 * Returns: 0, a negative value in case of an error.
1667 int scols_table_set_termheight(struct libscols_table
*tb
, size_t height
)
1669 DBG(TAB
, ul_debugobj(tb
, "set terminatl height: %zu", height
));
1670 tb
->termheight
= height
;
1675 * scols_table_get_termheight
1678 * Returns: terminal height (number of lines).
1682 size_t scols_table_get_termheight(const struct libscols_table
*tb
)
1684 return tb
->termheight
;