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 already initialized! */
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
)
273 if (tb
->dflt_sort_column
== cl
)
274 tb
->dflt_sort_column
= NULL
;
276 DBG(TAB
, ul_debugobj(tb
, "remove column"));
277 list_del_init(&cl
->cl_columns
);
280 scols_unref_column(cl
);
285 * scols_table_remove_columns:
286 * @tb: a pointer to a struct libscols_table instance
288 * Removes all of @tb's columns.
290 * Returns: 0, a negative number in case of an error.
292 int scols_table_remove_columns(struct libscols_table
*tb
)
294 if (!tb
|| !list_empty(&tb
->tb_lines
))
297 DBG(TAB
, ul_debugobj(tb
, "remove all columns"));
298 while (!list_empty(&tb
->tb_columns
)) {
299 struct libscols_column
*cl
= list_entry(tb
->tb_columns
.next
,
300 struct libscols_column
, cl_columns
);
301 scols_table_remove_column(tb
, cl
);
307 * scols_table_move_column:
309 * @pre: column before the column
310 * @cl: column to move
312 * Move the @cl behind @pre. If the @pre is NULL then the @col is the first
313 * column in the table.
317 * Returns: 0, a negative number in case of an error.
319 int scols_table_move_column(struct libscols_table
*tb
,
320 struct libscols_column
*pre
,
321 struct libscols_column
*cl
)
323 struct list_head
*head
;
324 struct libscols_iter itr
;
325 struct libscols_column
*p
;
326 struct libscols_line
*ln
;
327 size_t n
= 0, oldseq
;
332 if (pre
&& pre
->seqnum
+ 1 == cl
->seqnum
)
334 if (pre
== NULL
&& cl
->seqnum
== 0)
337 DBG(TAB
, ul_debugobj(tb
, "move column %zu behind %zu",
338 cl
->seqnum
, pre
? pre
->seqnum
: 0));
340 list_del_init(&cl
->cl_columns
); /* remove from old position */
342 head
= pre
? &pre
->cl_columns
: &tb
->tb_columns
;
343 list_add(&cl
->cl_columns
, head
); /* add to the new place */
347 /* fix seq. numbers */
348 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
349 while (scols_table_next_column(tb
, &itr
, &p
) == 0)
352 /* move data in lines */
353 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
354 while (scols_table_next_line(tb
, &itr
, &ln
) == 0)
355 scols_line_move_cells(ln
, cl
->seqnum
, oldseq
);
360 * scols_table_new_column:
362 * @name: column header
363 * @whint: column width hint (absolute width: N > 1; relative width: 0 < N < 1)
364 * @flags: flags integer
366 * This is shortcut for
369 * <programlisting language="C">
370 * cl = scols_new_column();
371 * scols_column_set_....(cl, ...);
372 * scols_table_add_column(tb, cl);
376 * The column width is possible to define by:
380 * whint: 0 < N < 1 : relative width, percent of terminal width
382 * whint: N >= 1 : absolute width, empty column will be truncated to
383 * the column header width if no specified STRICTWIDTH flag
387 * Note that if table has disabled "maxout" flag (disabled by default) than
388 * relative width is used as a hint only. It's possible that column will be
389 * narrow if the specified size is too large for column data.
392 * If the width of all columns is greater than terminal width then library
393 * tries to reduce width of the individual columns. It's done in three stages:
395 * 1. reduce columns with SCOLS_FL_TRUNC flag and with relative width if the
396 * width is greater than width defined by @whint (@whint * terminal_width)
398 * 2. reduce all columns with SCOLS_FL_TRUNC flag
400 * 3. reduce all columns with relative width
402 * The next stage is always used if the previous stage is unsuccessful. Note
403 * that SCOLS_FL_WRAP is interpreted as SCOLS_FL_TRUNC when calculate column
404 * width (if custom wrap function is not specified), but the final text is not
405 * truncated, but wrapped to multi-line cell.
408 * The column is necessary to address by sequential number. The first defined
409 * column has the colnum = 0. For example:
412 * <programlisting language="C">
413 * scols_table_new_column(tab, "FOO", 0.5, 0); // colnum = 0
414 * scols_table_new_column(tab, "BAR", 0.5, 0); // colnum = 1
417 * scols_line_get_cell(line, 0); // FOO column
418 * scols_line_get_cell(line, 1); // BAR column
422 * Returns: newly allocated column
424 struct libscols_column
*scols_table_new_column(struct libscols_table
*tb
,
429 struct libscols_column
*cl
;
434 DBG(TAB
, ul_debugobj(tb
, "new column name=%s, whint=%g, flags=0x%04x",
435 name
, whint
, flags
));
436 cl
= scols_new_column();
440 if (name
&& scols_column_set_name(cl
, name
))
442 scols_column_set_whint(cl
, whint
);
443 scols_column_set_flags(cl
, flags
);
445 if (scols_table_add_column(tb
, cl
)) /* this increments column ref-counter */
448 scols_unref_column(cl
);
451 scols_unref_column(cl
);
456 * scols_table_next_column:
457 * @tb: a pointer to a struct libscols_table instance
458 * @itr: a pointer to a struct libscols_iter instance
459 * @cl: a pointer to a pointer to a struct libscols_column instance
461 * Returns the next column of @tb via @cl.
463 * Returns: 0, a negative value in case of an error.
465 int scols_table_next_column(struct libscols_table
*tb
,
466 struct libscols_iter
*itr
,
467 struct libscols_column
**cl
)
471 if (!tb
|| !itr
|| !cl
)
476 SCOLS_ITER_INIT(itr
, &tb
->tb_columns
);
477 if (itr
->p
!= itr
->head
) {
478 SCOLS_ITER_ITERATE(itr
, *cl
, struct libscols_column
, cl_columns
);
486 * scols_table_set_columns_iter:
491 * Sets @iter to the position of @cl in the file @tb.
493 * Returns: 0 on success, negative number in case of error.
497 int scols_table_set_columns_iter(
498 struct libscols_table
*tb
,
499 struct libscols_iter
*itr
,
500 struct libscols_column
*cl
)
502 if (!tb
|| !itr
|| !cl
)
508 SCOLS_ITER_INIT(itr
, &tb
->tb_columns
);
509 itr
->p
= &cl
->cl_columns
;
515 * scols_table_get_ncols:
518 * Returns: the ncols table member.
520 size_t scols_table_get_ncols(const struct libscols_table
*tb
)
526 * scols_table_get_nlines:
529 * Returns: the nlines table member.
531 size_t scols_table_get_nlines(const struct libscols_table
*tb
)
537 int scols_table_set_cursor(struct libscols_table
*tb
,
538 struct libscols_line
*ln
,
539 struct libscols_column
*cl
,
540 struct libscols_cell
*ce
)
553 * scols_table_get_cursor:
555 * @ln: returns current line (optional)
556 * @cl: returns current column (optional)
557 * @ce: returns current cell (optional)
559 * Returns: 0 on success, negative number in case of error.
563 int scols_table_get_cursor(struct libscols_table
*tb
,
564 struct libscols_line
**ln
,
565 struct libscols_column
**cl
,
566 struct libscols_cell
**ce
)
574 *cl
= tb
->cur_column
;
581 * scols_table_set_stream:
583 * @stream: output stream
585 * Sets the output stream for table @tb.
587 * Returns: 0, a negative number in case of an error.
589 int scols_table_set_stream(struct libscols_table
*tb
, FILE *stream
)
595 DBG(TAB
, ul_debugobj(tb
, "setting alternative stream"));
601 * scols_table_get_stream:
604 * Gets the output stream for table @tb.
606 * Returns: stream pointer, NULL in case of an error or an unset stream.
608 FILE *scols_table_get_stream(const struct libscols_table
*tb
)
614 * scols_table_reduce_termwidth:
618 * If necessary then libsmartcols use all terminal width, the @reduce setting
619 * provides extra space (for example for borders in ncurses applications).
621 * The @reduce must be smaller than terminal width, otherwise it's silently
622 * ignored. The reduction is not applied when STDOUT_FILENO is not terminal.
624 * Note that after output initialization (scols_table_print_* calls) the width
625 * will be reduced, this behavior affects subsequenced scols_table_get_termwidth()
628 * Returns: 0, a negative value in case of an error.
630 int scols_table_reduce_termwidth(struct libscols_table
*tb
, size_t reduce
)
635 DBG(TAB
, ul_debugobj(tb
, "reduce terminal width: %zu", reduce
));
636 tb
->termreduce
= reduce
;
641 * scols_table_get_column:
643 * @n: number of column (0..N)
645 * Returns: pointer to column or NULL
647 struct libscols_column
*scols_table_get_column(struct libscols_table
*tb
,
650 struct libscols_iter itr
;
651 struct libscols_column
*cl
;
658 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
659 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
667 * scols_table_get_column_ny_name
671 * Returns: pointer to column or NULL
675 struct libscols_column
*scols_table_get_column_by_name(
676 struct libscols_table
*tb
, const char *name
)
678 struct libscols_iter itr
;
679 struct libscols_column
*cl
;
684 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
685 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
686 const char *cn
= scols_column_get_name(cl
);
688 if (cn
&& strcmp(cn
, name
) == 0)
692 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
693 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
694 const char *cn
= scols_column_get_name_as_shellvar(cl
);
696 if (cn
&& strcmp(cn
, name
) == 0)
705 * scols_table_add_line:
709 * Note that this function calls scols_line_alloc_cells() if number
710 * of the cells in the line is too small for @tb.
712 * Returns: 0, a negative value in case of an error.
714 int scols_table_add_line(struct libscols_table
*tb
, struct libscols_line
*ln
)
719 if (!list_empty(&ln
->ln_lines
))
722 if (tb
->ncols
> ln
->ncells
) {
723 int rc
= scols_line_alloc_cells(ln
, tb
->ncols
);
728 DBG(TAB
, ul_debugobj(tb
, "add line"));
729 list_add_tail(&ln
->ln_lines
, &tb
->tb_lines
);
730 ln
->seqnum
= tb
->nlines
++;
736 * scols_table_remove_line:
740 * Note that this function does not destroy the parent<->child relationship between lines.
741 * You have to call scols_line_remove_child()
743 * Returns: 0, a negative value in case of an error.
745 int scols_table_remove_line(struct libscols_table
*tb
,
746 struct libscols_line
*ln
)
751 DBG(TAB
, ul_debugobj(tb
, "remove line"));
752 list_del_init(&ln
->ln_lines
);
754 scols_unref_line(ln
);
759 * scols_table_remove_lines:
762 * This empties the table and also destroys all the parent<->child relationships.
764 void scols_table_remove_lines(struct libscols_table
*tb
)
769 DBG(TAB
, ul_debugobj(tb
, "remove all lines"));
770 while (!list_empty(&tb
->tb_lines
)) {
771 struct libscols_line
*ln
= list_entry(tb
->tb_lines
.next
,
772 struct libscols_line
, ln_lines
);
774 scols_line_remove_child(ln
->parent
, ln
);
775 scols_table_remove_line(tb
, ln
);
780 * scols_table_next_line:
781 * @tb: a pointer to a struct libscols_table instance
782 * @itr: a pointer to a struct libscols_iter instance
783 * @ln: a pointer to a pointer to a struct libscols_line instance
785 * Finds the next line and returns a pointer to it via @ln.
787 * Returns: 0, a negative value in case of an error.
789 int scols_table_next_line(struct libscols_table
*tb
,
790 struct libscols_iter
*itr
,
791 struct libscols_line
**ln
)
795 if (!tb
|| !itr
|| !ln
)
800 SCOLS_ITER_INIT(itr
, &tb
->tb_lines
);
801 if (itr
->p
!= itr
->head
) {
802 SCOLS_ITER_ITERATE(itr
, *ln
, struct libscols_line
, ln_lines
);
810 * scols_table_new_line:
812 * @parent: parental line or NULL
814 * This is shortcut for
817 * <programlisting language="C">
818 * ln = scols_new_line();
819 * scols_table_add_line(tb, ln);
820 * scols_line_add_child(parent, ln);
824 * Returns: newly allocate line
826 struct libscols_line
*scols_table_new_line(struct libscols_table
*tb
,
827 struct libscols_line
*parent
)
829 struct libscols_line
*ln
;
834 ln
= scols_new_line();
838 if (scols_table_add_line(tb
, ln
))
841 scols_line_add_child(parent
, ln
);
843 scols_unref_line(ln
); /* ref-counter incremented by scols_table_add_line() */
846 scols_unref_line(ln
);
851 * scols_table_get_line:
853 * @n: column number (0..N)
855 * Returns: a line or NULL
857 struct libscols_line
*scols_table_get_line(struct libscols_table
*tb
,
860 struct libscols_iter itr
;
861 struct libscols_line
*ln
;
868 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
869 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
880 * Creates a new independent table copy, except struct libscols_symbols that
881 * are shared between the tables.
883 * Returns: a newly allocated copy of @tb
885 struct libscols_table
*scols_copy_table(struct libscols_table
*tb
)
887 struct libscols_table
*ret
;
888 struct libscols_line
*ln
;
889 struct libscols_column
*cl
;
890 struct libscols_iter itr
;
894 ret
= scols_new_table();
898 DBG(TAB
, ul_debugobj(tb
, "copy"));
901 scols_table_set_symbols(ret
, tb
->symbols
);
904 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
905 while (scols_table_next_column(tb
, &itr
, &cl
) == 0) {
906 cl
= scols_copy_column(cl
);
909 if (scols_table_add_column(ret
, cl
))
911 scols_unref_column(cl
);
915 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
916 while (scols_table_next_line(tb
, &itr
, &ln
) == 0) {
917 struct libscols_line
*newln
= scols_copy_line(ln
);
920 if (scols_table_add_line(ret
, newln
))
923 struct libscols_line
*p
=
924 scols_table_get_line(ret
, ln
->parent
->seqnum
);
926 scols_line_add_child(p
, newln
);
928 scols_unref_line(newln
);
932 if (scols_table_set_column_separator(ret
, tb
->colsep
) ||
933 scols_table_set_line_separator(ret
, tb
->linesep
))
938 scols_unref_table(ret
);
943 * scols_table_set_default_symbols:
946 * The library check the current environment to select ASCII or UTF8 symbols.
947 * This default behavior could be controlled by scols_table_enable_ascii().
949 * Use scols_table_set_symbols() to unset symbols or use your own setting.
951 * Returns: 0, a negative value in case of an error.
955 int scols_table_set_default_symbols(struct libscols_table
*tb
)
957 struct libscols_symbols
*sy
;
963 DBG(TAB
, ul_debugobj(tb
, "setting default symbols"));
965 sy
= scols_new_symbols();
969 #if defined(HAVE_WIDECHAR)
970 if (!scols_table_is_ascii(tb
) &&
971 !strcmp(nl_langinfo(CODESET
), "UTF-8")) {
973 scols_symbols_set_branch(sy
, UTF_VR UTF_H
);
974 scols_symbols_set_vertical(sy
, UTF_V
" ");
975 scols_symbols_set_right(sy
, UTF_UR UTF_H
);
977 scols_symbols_set_group_horizontal(sy
, UTF_H3
);
978 scols_symbols_set_group_vertical(sy
, UTF_V3
);
980 scols_symbols_set_group_first_member(sy
, UTF_DR UTF_H3 UTF_TR
);
981 scols_symbols_set_group_last_member(sy
, UTF_UR UTF_DH UTF_TR
);
982 scols_symbols_set_group_middle_member(sy
, UTF_VR UTF_H3 UTF_TR
);
983 scols_symbols_set_group_last_child(sy
, UTF_UR UTF_H3
);
984 scols_symbols_set_group_middle_child(sy
, UTF_VR UTF_H3
);
989 scols_symbols_set_branch(sy
, "|-");
990 scols_symbols_set_vertical(sy
, "| ");
991 scols_symbols_set_right(sy
, "`-");
993 scols_symbols_set_group_horizontal(sy
, "-");
994 scols_symbols_set_group_vertical(sy
, "|");
996 scols_symbols_set_group_first_member(sy
, ",->");
997 scols_symbols_set_group_last_member(sy
, "'->");
998 scols_symbols_set_group_middle_member(sy
, "|->");
999 scols_symbols_set_group_last_child(sy
, "`-");
1000 scols_symbols_set_group_middle_child(sy
, "|-");
1002 scols_symbols_set_title_padding(sy
, " ");
1003 scols_symbols_set_cell_padding(sy
, " ");
1005 rc
= scols_table_set_symbols(tb
, sy
);
1006 scols_unref_symbols(sy
);
1012 * scols_table_set_symbols:
1014 * @sy: symbols or NULL
1016 * Add a reference to @sy from the table. The symbols are used by library to
1017 * draw tree output. If no symbols are used for the table then library creates
1018 * default temporary symbols to draw output by scols_table_set_default_symbols().
1020 * If @sy is NULL then remove reference from the currently used symbols.
1022 * Returns: 0, a negative value in case of an error.
1024 int scols_table_set_symbols(struct libscols_table
*tb
,
1025 struct libscols_symbols
*sy
)
1032 DBG(TAB
, ul_debugobj(tb
, "remove symbols reference"));
1033 scols_unref_symbols(tb
->symbols
);
1038 if (sy
) { /* ref user defined */
1039 DBG(TAB
, ul_debugobj(tb
, "set symbols"));
1041 scols_ref_symbols(sy
);
1047 * scols_table_get_symbols:
1050 * Returns: pointer to symbols table.
1054 struct libscols_symbols
*scols_table_get_symbols(const struct libscols_table
*tb
)
1060 * scols_table_enable_nolinesep:
1064 * Enable/disable line separator printing. This is useful if you want to
1065 * re-printing the same line more than once (e.g. progress bar). Don't use it
1066 * if you're not sure.
1068 * Note that for the last line in the table the separator is disabled at all.
1069 * The library differentiate between table terminator and line terminator
1070 * (although for standard output \n byte is used in both cases).
1072 * Returns: 0 on success, negative number in case of an error.
1074 int scols_table_enable_nolinesep(struct libscols_table
*tb
, int enable
)
1079 DBG(TAB
, ul_debugobj(tb
, "nolinesep: %s", enable
? "ENABLE" : "DISABLE"));
1080 tb
->no_linesep
= enable
? 1 : 0;
1085 * scols_table_is_nolinesep:
1086 * @tb: a pointer to a struct libscols_table instance
1088 * Returns: 1 if line separator printing is disabled.
1092 int scols_table_is_nolinesep(const struct libscols_table
*tb
)
1094 return tb
->no_linesep
;
1098 * scols_table_enable_colors:
1102 * Enable/disable colors.
1104 * Returns: 0 on success, negative number in case of an error.
1106 int scols_table_enable_colors(struct libscols_table
*tb
, int enable
)
1111 DBG(TAB
, ul_debugobj(tb
, "colors: %s", enable
? "ENABLE" : "DISABLE"));
1112 tb
->colors_wanted
= enable
;
1117 * scols_table_enable_raw:
1121 * Enable/disable raw output format. The parsable output formats
1122 * (export, raw, JSON, ...) are mutually exclusive.
1124 * Returns: 0 on success, negative number in case of an error.
1126 int scols_table_enable_raw(struct libscols_table
*tb
, int enable
)
1131 DBG(TAB
, ul_debugobj(tb
, "raw: %s", enable
? "ENABLE" : "DISABLE"));
1133 tb
->format
= SCOLS_FMT_RAW
;
1134 else if (tb
->format
== SCOLS_FMT_RAW
)
1140 * scols_table_enable_json:
1144 * Enable/disable JSON output format. The parsable output formats
1145 * (export, raw, JSON, ...) are mutually exclusive.
1147 * Returns: 0 on success, negative number in case of an error.
1151 int scols_table_enable_json(struct libscols_table
*tb
, int enable
)
1156 DBG(TAB
, ul_debugobj(tb
, "json: %s", enable
? "ENABLE" : "DISABLE"));
1158 tb
->format
= SCOLS_FMT_JSON
;
1159 else if (tb
->format
== SCOLS_FMT_JSON
)
1165 * scols_table_enable_export:
1169 * Enable/disable export output format (COLUMNAME="value" ...).
1170 * The parsable output formats (export and raw) are mutually exclusive.
1172 * See also scols_table_enable_shellvar(). Note that in version 2.37 (and only
1173 * in this version) scols_table_enable_shellvar() functionality has been
1174 * automatically enabled for "export" format. This behavior has been reverted
1175 * in version 2.38 due to backward compatibility issues. Now it's necessary to
1176 * explicitly call scols_table_enable_shellvar().
1178 * Returns: 0 on success, negative number in case of an error.
1180 int scols_table_enable_export(struct libscols_table
*tb
, int enable
)
1185 DBG(TAB
, ul_debugobj(tb
, "export: %s", enable
? "ENABLE" : "DISABLE"));
1187 tb
->format
= SCOLS_FMT_EXPORT
;
1188 else if (tb
->format
== SCOLS_FMT_EXPORT
)
1194 * scols_table_enable_shellvar:
1198 * Force library to print column names to be compatible with shell requirements
1199 * to variable names. For example "1FOO%" will be printed as "_1FOO_PCT".
1201 * Returns: 0 on success, negative number in case of an error.
1205 int scols_table_enable_shellvar(struct libscols_table
*tb
, int enable
)
1210 DBG(TAB
, ul_debugobj(tb
, "shellvar: %s", enable
? "ENABLE" : "DISABLE"));
1211 tb
->is_shellvar
= enable
? 1 : 0;
1217 * scols_table_enable_ascii:
1221 * The ASCII-only output is relevant for tree-like outputs. The library
1222 * checks if the current environment is UTF8 compatible by default. This
1223 * function overrides this check and force the library to use ASCII chars
1226 * If a custom libcols_symbols are specified (see scols_table_set_symbols()
1227 * then ASCII flag setting is ignored.
1229 * Returns: 0 on success, negative number in case of an error.
1231 int scols_table_enable_ascii(struct libscols_table
*tb
, int enable
)
1236 DBG(TAB
, ul_debugobj(tb
, "ascii: %s", enable
? "ENABLE" : "DISABLE"));
1237 tb
->ascii
= enable
? 1 : 0;
1242 * scols_table_enable_noheadings:
1246 * Enable/disable header line.
1248 * Returns: 0 on success, negative number in case of an error.
1250 int scols_table_enable_noheadings(struct libscols_table
*tb
, int enable
)
1254 DBG(TAB
, ul_debugobj(tb
, "noheading: %s", enable
? "ENABLE" : "DISABLE"));
1255 tb
->no_headings
= enable
? 1 : 0;
1260 * scols_table_enable_header_repeat:
1264 * Enable/disable header line repeat. The header line is printed only once by
1265 * default. Note that the flag will be silently ignored and disabled if the
1266 * output is not on terminal or output format is JSON, raw, etc.
1268 * Returns: 0 on success, negative number in case of an error.
1272 int scols_table_enable_header_repeat(struct libscols_table
*tb
, int enable
)
1276 DBG(TAB
, ul_debugobj(tb
, "header-repeat: %s", enable
? "ENABLE" : "DISABLE"));
1277 tb
->header_repeat
= enable
? 1 : 0;
1282 * scols_table_enable_maxout:
1286 * The extra space after last column is ignored by default. The output
1287 * maximization add padding for all columns.
1289 * This setting is mutually exclusive to scols_table_enable_minout().
1291 * Returns: 0 on success, negative number in case of an error.
1293 int scols_table_enable_maxout(struct libscols_table
*tb
, int enable
)
1295 if (!tb
|| tb
->minout
)
1298 DBG(TAB
, ul_debugobj(tb
, "maxout: %s", enable
? "ENABLE" : "DISABLE"));
1299 tb
->maxout
= enable
? 1 : 0;
1304 * scols_table_enable_minout:
1308 * Force library to terminate line after last column with data. The extra
1309 * padding is not added to the empty cells at the end of the line. The default is fill
1310 * trailing empty cells except the last line cell.
1312 * This setting is mutually exclusive to scols_table_enable_maxout().
1314 * Returns: 0 on success, negative number in case of an error.
1318 int scols_table_enable_minout(struct libscols_table
*tb
, int enable
)
1320 if (!tb
|| tb
->maxout
)
1323 DBG(TAB
, ul_debugobj(tb
, "minout: %s", enable
? "ENABLE" : "DISABLE"));
1324 tb
->minout
= enable
? 1 : 0;
1329 * scols_table_enable_nowrap:
1333 * Never continue on next line, remove last column(s) when too large, truncate last column.
1335 * Returns: 0 on success, negative number in case of an error.
1339 int scols_table_enable_nowrap(struct libscols_table
*tb
, int enable
)
1343 DBG(TAB
, ul_debugobj(tb
, "nowrap: %s", enable
? "ENABLE" : "DISABLE"));
1344 tb
->no_wrap
= enable
? 1 : 0;
1349 * scols_table_is_nowrap:
1350 * @tb: a pointer to a struct libscols_table instance
1352 * Returns: 1 if nowrap is enabled.
1356 int scols_table_is_nowrap(const struct libscols_table
*tb
)
1362 * scols_table_enable_noencoding:
1366 * The library encode non-printable and control chars by \xHEX by default.
1368 * Returns: 0 on success, negative number in case of an error.
1372 int scols_table_enable_noencoding(struct libscols_table
*tb
, int enable
)
1376 DBG(TAB
, ul_debugobj(tb
, "encoding: %s", enable
? "ENABLE" : "DISABLE"));
1377 tb
->no_encode
= enable
? 1 : 0;
1382 * scols_table_is_noencoding:
1383 * @tb: a pointer to a struct libscols_table instance
1385 * Returns: 1 if encoding is disabled.
1389 int scols_table_is_noencoding(const struct libscols_table
*tb
)
1391 return tb
->no_encode
;
1395 * scols_table_colors_wanted:
1398 * Returns: 1 if colors are enabled.
1400 int scols_table_colors_wanted(const struct libscols_table
*tb
)
1402 return tb
->colors_wanted
;
1406 * scols_table_is_empty:
1409 * Returns: 1 if the table is empty.
1411 int scols_table_is_empty(const struct libscols_table
*tb
)
1417 * scols_table_is_ascii:
1420 * Returns: 1 if ASCII tree is enabled.
1422 int scols_table_is_ascii(const struct libscols_table
*tb
)
1428 * scols_table_is_noheadings:
1431 * Returns: 1 if header output is disabled.
1433 int scols_table_is_noheadings(const struct libscols_table
*tb
)
1435 return tb
->no_headings
;
1439 * scols_table_is_header_repeat
1442 * Returns: 1 if header repeat is enabled.
1446 int scols_table_is_header_repeat(const struct libscols_table
*tb
)
1448 return tb
->header_repeat
;
1452 * scols_table_is_export:
1455 * Returns: 1 if export output format is enabled.
1457 int scols_table_is_export(const struct libscols_table
*tb
)
1459 return tb
->format
== SCOLS_FMT_EXPORT
;
1463 * scols_table_is_shellvar:
1466 * Returns: 1 if column names has to be compatible with shell requirements
1471 int scols_table_is_shellvar(const struct libscols_table
*tb
)
1473 return tb
->is_shellvar
;
1477 * scols_table_is_raw:
1480 * Returns: 1 if raw output format is enabled.
1482 int scols_table_is_raw(const struct libscols_table
*tb
)
1484 return tb
->format
== SCOLS_FMT_RAW
;
1488 * scols_table_is_json:
1491 * Returns: 1 if JSON output format is enabled.
1495 int scols_table_is_json(const struct libscols_table
*tb
)
1497 return tb
->format
== SCOLS_FMT_JSON
;
1501 * scols_table_is_maxout
1504 * Returns: 1 if output maximization is enabled or 0
1506 int scols_table_is_maxout(const struct libscols_table
*tb
)
1512 * scols_table_is_minout
1515 * Returns: 1 if output minimization is enabled or 0
1519 int scols_table_is_minout(const struct libscols_table
*tb
)
1525 * scols_table_is_tree:
1528 * Returns: returns 1 tree-like output is expected.
1530 int scols_table_is_tree(const struct libscols_table
*tb
)
1532 return tb
->ntreecols
> 0;
1536 * scols_table_set_column_separator:
1540 * Sets the column separator of @tb to @sep.
1542 * Returns: 0, a negative value in case of an error.
1544 int scols_table_set_column_separator(struct libscols_table
*tb
, const char *sep
)
1546 return strdup_to_struct_member(tb
, colsep
, sep
);
1550 * scols_table_set_line_separator:
1554 * Sets the line separator of @tb to @sep.
1556 * Returns: 0, a negative value in case of an error.
1558 int scols_table_set_line_separator(struct libscols_table
*tb
, const char *sep
)
1560 return strdup_to_struct_member(tb
, linesep
, sep
);
1564 * scols_table_get_column_separator:
1567 * Returns: @tb column separator, NULL in case of an error
1569 const char *scols_table_get_column_separator(const struct libscols_table
*tb
)
1575 * scols_table_get_line_separator:
1578 * Returns: @tb line separator, NULL in case of an error
1580 const char *scols_table_get_line_separator(const struct libscols_table
*tb
)
1584 /* for lines in the struct libscols_line->ln_lines list */
1585 static int cells_cmp_wrapper_lines(struct list_head
*a
, struct list_head
*b
, void *data
)
1587 struct libscols_column
*cl
= (struct libscols_column
*) data
;
1588 struct libscols_line
*ra
, *rb
;
1589 struct libscols_cell
*ca
, *cb
;
1595 ra
= list_entry(a
, struct libscols_line
, ln_lines
);
1596 rb
= list_entry(b
, struct libscols_line
, ln_lines
);
1597 ca
= scols_line_get_cell(ra
, cl
->seqnum
);
1598 cb
= scols_line_get_cell(rb
, cl
->seqnum
);
1600 return cl
->cmpfunc(ca
, cb
, cl
->cmpfunc_data
);
1603 /* for lines in the struct libscols_line->ln_children list */
1604 static int cells_cmp_wrapper_children(struct list_head
*a
, struct list_head
*b
, void *data
)
1606 struct libscols_column
*cl
= (struct libscols_column
*) data
;
1607 struct libscols_line
*ra
, *rb
;
1608 struct libscols_cell
*ca
, *cb
;
1614 ra
= list_entry(a
, struct libscols_line
, ln_children
);
1615 rb
= list_entry(b
, struct libscols_line
, ln_children
);
1616 ca
= scols_line_get_cell(ra
, cl
->seqnum
);
1617 cb
= scols_line_get_cell(rb
, cl
->seqnum
);
1619 return cl
->cmpfunc(ca
, cb
, cl
->cmpfunc_data
);
1623 static int sort_line_children(struct libscols_line
*ln
, struct libscols_column
*cl
)
1625 struct list_head
*p
;
1627 if (!list_empty(&ln
->ln_branch
)) {
1628 list_for_each(p
, &ln
->ln_branch
) {
1629 struct libscols_line
*chld
=
1630 list_entry(p
, struct libscols_line
, ln_children
);
1631 sort_line_children(chld
, cl
);
1634 list_sort(&ln
->ln_branch
, cells_cmp_wrapper_children
, cl
);
1637 if (is_first_group_member(ln
)) {
1638 list_for_each(p
, &ln
->group
->gr_children
) {
1639 struct libscols_line
*chld
=
1640 list_entry(p
, struct libscols_line
, ln_children
);
1641 sort_line_children(chld
, cl
);
1644 list_sort(&ln
->group
->gr_children
, cells_cmp_wrapper_children
, cl
);
1650 static int __scols_sort_tree(struct libscols_table
*tb
, struct libscols_column
*cl
)
1652 struct libscols_line
*ln
;
1653 struct libscols_iter itr
;
1655 if (!tb
|| !cl
|| !cl
->cmpfunc
)
1658 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
1659 while (scols_table_next_line(tb
, &itr
, &ln
) == 0)
1660 sort_line_children(ln
, cl
);
1667 * @cl: order by this column or NULL
1669 * Orders the table by the column. See also scols_column_set_cmpfunc(). If the
1670 * tree output is enabled then children in the tree are recursively sorted too.
1672 * The column @cl is saved as the default sort column to the @tb and the next time
1673 * is possible to call scols_sort_table(tb, NULL). The saved column is also used by
1674 * scols_sort_table_by_tree().
1676 * Returns: 0, a negative value in case of an error.
1678 int scols_sort_table(struct libscols_table
*tb
, struct libscols_column
*cl
)
1683 cl
= tb
->dflt_sort_column
;
1684 if (!cl
|| !cl
->cmpfunc
)
1687 DBG(TAB
, ul_debugobj(tb
, "sorting table by %zu column", cl
->seqnum
));
1688 list_sort(&tb
->tb_lines
, cells_cmp_wrapper_lines
, cl
);
1690 if (scols_table_is_tree(tb
))
1691 __scols_sort_tree(tb
, cl
);
1693 if (cl
&& cl
!= tb
->dflt_sort_column
)
1694 tb
->dflt_sort_column
= cl
;
1700 * Move all @ln's children after @ln in the table.
1702 static struct libscols_line
*move_line_and_children(struct libscols_line
*ln
, struct libscols_line
*pre
)
1705 list_del_init(&ln
->ln_lines
); /* remove from old position */
1706 list_add(&ln
->ln_lines
, &pre
->ln_lines
); /* add to the new place (after @pre) */
1710 if (!list_empty(&ln
->ln_branch
)) {
1711 struct list_head
*p
;
1713 list_for_each(p
, &ln
->ln_branch
) {
1714 struct libscols_line
*chld
=
1715 list_entry(p
, struct libscols_line
, ln_children
);
1716 pre
= move_line_and_children(chld
, pre
);
1724 * scols_sort_table_by_tree:
1727 * Reorders lines in the table by parent->child relation. Note that order of
1728 * the lines in the table is independent on the tree hierarchy by default.
1730 * The children of the lines are sorted according to the default sort column
1731 * if scols_sort_table() has been previously called.
1735 * Returns: 0, a negative value in case of an error.
1737 int scols_sort_table_by_tree(struct libscols_table
*tb
)
1739 struct libscols_line
*ln
;
1740 struct libscols_iter itr
;
1745 DBG(TAB
, ul_debugobj(tb
, "sorting table by tree"));
1747 if (tb
->dflt_sort_column
)
1748 __scols_sort_tree(tb
, tb
->dflt_sort_column
);
1750 scols_reset_iter(&itr
, SCOLS_ITER_FORWARD
);
1751 while (scols_table_next_line(tb
, &itr
, &ln
) == 0)
1752 move_line_and_children(ln
, NULL
);
1759 * scols_table_set_termforce:
1761 * @force: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO}
1763 * Forces library to use stdout as terminal, non-terminal or use automatic
1764 * detection (default).
1766 * Returns: 0, a negative value in case of an error.
1770 int scols_table_set_termforce(struct libscols_table
*tb
, int force
)
1774 tb
->termforce
= force
;
1779 * scols_table_get_termforce:
1782 * Returns: SCOLS_TERMFORCE_{NEVER,ALWAYS,AUTO} or a negative value in case of an error.
1786 int scols_table_get_termforce(const struct libscols_table
*tb
)
1788 return tb
->termforce
;
1792 * scols_table_set_termwidth
1794 * @width: terminal width
1796 * The library automatically detects terminal width or defaults to 80 chars if
1797 * detections is unsuccessful. This function override this behaviour.
1799 * Returns: 0, a negative value in case of an error.
1803 int scols_table_set_termwidth(struct libscols_table
*tb
, size_t width
)
1805 DBG(TAB
, ul_debugobj(tb
, "set terminatl width: %zu", width
));
1806 tb
->termwidth
= width
;
1811 * scols_table_get_termwidth
1814 * Returns: terminal width.
1816 size_t scols_table_get_termwidth(const struct libscols_table
*tb
)
1818 return tb
->termwidth
;
1822 * scols_table_set_termheight
1824 * @height: terminal height (number of lines)
1826 * The library automatically detects terminal height or defaults to 24 lines if
1827 * detections is unsuccessful. This function override this behaviour.
1829 * Returns: 0, a negative value in case of an error.
1833 int scols_table_set_termheight(struct libscols_table
*tb
, size_t height
)
1835 DBG(TAB
, ul_debugobj(tb
, "set terminatl height: %zu", height
));
1836 tb
->termheight
= height
;
1841 * scols_table_get_termheight
1844 * Returns: terminal height (number of lines).
1848 size_t scols_table_get_termheight(const struct libscols_table
*tb
)
1850 return tb
->termheight
;