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