1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include <sys/types.h>
7 
8 #include "json.h"
9 #include "macro.h"
10 #include "pager.h"
11 
12 typedef enum TableDataType {
13         TABLE_EMPTY,
14         TABLE_STRING,
15         TABLE_STRV,
16         TABLE_STRV_WRAPPED,
17         TABLE_PATH,
18         TABLE_BOOLEAN,
19         TABLE_BOOLEAN_CHECKMARK,
20         TABLE_TIMESTAMP,
21         TABLE_TIMESTAMP_UTC,
22         TABLE_TIMESTAMP_RELATIVE,
23         TABLE_TIMESPAN,
24         TABLE_TIMESPAN_MSEC,
25         TABLE_SIZE,
26         TABLE_BPS,
27         TABLE_INT,
28         TABLE_INT8,
29         TABLE_INT16,
30         TABLE_INT32,
31         TABLE_INT64,
32         TABLE_UINT,
33         TABLE_UINT8,
34         TABLE_UINT16,
35         TABLE_UINT32,
36         TABLE_UINT64,
37         TABLE_UINT64_HEX,
38         TABLE_PERCENT,
39         TABLE_IFINDEX,
40         TABLE_IN_ADDR,  /* Takes a union in_addr_union (or a struct in_addr) */
41         TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */
42         TABLE_ID128,
43         TABLE_UUID,
44         TABLE_UID,
45         TABLE_GID,
46         TABLE_PID,
47         TABLE_SIGNAL,
48         TABLE_MODE,     /* as in UNIX file mode (mode_t), in typical octal output */
49         _TABLE_DATA_TYPE_MAX,
50 
51         /* The following are not really data types, but commands for table_add_cell_many() to make changes to
52          * a cell just added. */
53         TABLE_SET_MINIMUM_WIDTH,
54         TABLE_SET_MAXIMUM_WIDTH,
55         TABLE_SET_WEIGHT,
56         TABLE_SET_ALIGN_PERCENT,
57         TABLE_SET_ELLIPSIZE_PERCENT,
58         TABLE_SET_COLOR,
59         TABLE_SET_RGAP_COLOR,
60         TABLE_SET_BOTH_COLORS,
61         TABLE_SET_URL,
62         TABLE_SET_UPPERCASE,
63 
64         _TABLE_DATA_TYPE_INVALID = -EINVAL,
65 } TableDataType;
66 
67 typedef struct Table Table;
68 typedef struct TableCell TableCell;
69 
70 Table *table_new_internal(const char *first_header, ...) _sentinel_;
71 #define table_new(...) table_new_internal(__VA_ARGS__, NULL)
72 Table *table_new_raw(size_t n_columns);
73 Table *table_unref(Table *t);
74 
75 DEFINE_TRIVIAL_CLEANUP_FUNC(Table*, table_unref);
76 
77 int table_add_cell_full(Table *t, TableCell **ret_cell, TableDataType type, const void *data, size_t minimum_width, size_t maximum_width, unsigned weight, unsigned align_percent, unsigned ellipsize_percent);
table_add_cell(Table * t,TableCell ** ret_cell,TableDataType type,const void * data)78 static inline int table_add_cell(Table *t, TableCell **ret_cell, TableDataType type, const void *data) {
79         return table_add_cell_full(t, ret_cell, type, data, SIZE_MAX, SIZE_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
80 }
81 int table_add_cell_stringf(Table *t, TableCell **ret_cell, const char *format, ...) _printf_(3, 4);
82 
83 int table_fill_empty(Table *t, size_t until_column);
84 
85 int table_dup_cell(Table *t, TableCell *cell);
86 
87 int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width);
88 int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width);
89 int table_set_weight(Table *t, TableCell *cell, unsigned weight);
90 int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
91 int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
92 int table_set_color(Table *t, TableCell *cell, const char *color);
93 int table_set_rgap_color(Table *t, TableCell *cell, const char *color);
94 int table_set_url(Table *t, TableCell *cell, const char *url);
95 int table_set_uppercase(Table *t, TableCell *cell, bool b);
96 
97 int table_update(Table *t, TableCell *cell, TableDataType type, const void *data);
98 
99 int table_add_many_internal(Table *t, TableDataType first_type, ...);
100 #define table_add_many(t, ...) table_add_many_internal(t, __VA_ARGS__, _TABLE_DATA_TYPE_MAX)
101 
102 void table_set_header(Table *table, bool b);
103 void table_set_width(Table *t, size_t width);
104 void table_set_cell_height_max(Table *t, size_t height);
105 int table_set_empty_string(Table *t, const char *empty);
106 int table_set_display_internal(Table *t, size_t first_column, ...);
107 #define table_set_display(...) table_set_display_internal(__VA_ARGS__, SIZE_MAX)
108 int table_set_sort_internal(Table *t, size_t first_column, ...);
109 #define table_set_sort(...) table_set_sort_internal(__VA_ARGS__, SIZE_MAX)
110 int table_set_reverse(Table *t, size_t column, bool b);
111 int table_hide_column_from_display_internal(Table *t, ...);
112 #define table_hide_column_from_display(t, ...) table_hide_column_from_display_internal(t, __VA_ARGS__, (size_t) -1)
113 
114 int table_print(Table *t, FILE *f);
115 int table_format(Table *t, char **ret);
116 
TABLE_HEADER_CELL(size_t i)117 static inline TableCell* TABLE_HEADER_CELL(size_t i) {
118         return SIZE_TO_PTR(i + 1);
119 }
120 
121 size_t table_get_rows(Table *t);
122 size_t table_get_columns(Table *t);
123 
124 TableCell *table_get_cell(Table *t, size_t row, size_t column);
125 
126 const void *table_get(Table *t, TableCell *cell);
127 const void *table_get_at(Table *t, size_t row, size_t column);
128 
129 int table_to_json(Table *t, JsonVariant **ret);
130 int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags);
131 
132 int table_print_with_pager(Table *t, JsonFormatFlags json_format_flags, PagerFlags pager_flags, bool show_header);
133 
134 int table_set_json_field_name(Table *t, size_t column, const char *name);
135 
136 #define table_log_add_error(r) \
137         log_error_errno(r, "Failed to add cell(s) to table: %m")
138 
139 #define table_log_print_error(r) \
140         log_error_errno(r, "Failed to print table: %m")
141 
142 #define table_log_sort_error(r) \
143         log_error_errno(r, "Failed to sort table: %m")
144