summaryrefslogtreecommitdiff
path: root/src/shared/format-table.h
blob: 148418c70f6143a1ad0d3db7d6086ba8185ffc6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once

#include <stdbool.h>
#include <stdio.h>
#include <sys/types.h>

#include "json.h"
#include "macro.h"
#include "pager.h"

typedef enum TableDataType {
        TABLE_EMPTY,
        TABLE_STRING,
        TABLE_HEADER,              /* in regular mode: the cells in the first row, that carry the column names */
        TABLE_FIELD,               /* in vertical mode: the cells in the first column, that carry the field names */
        TABLE_STRV,
        TABLE_STRV_WRAPPED,
        TABLE_PATH,
        TABLE_PATH_BASENAME,       /* like TABLE_PATH, but display only last path element (i.e. the "basename") in regular output */
        TABLE_BOOLEAN,
        TABLE_BOOLEAN_CHECKMARK,
        TABLE_TIMESTAMP,
        TABLE_TIMESTAMP_UTC,
        TABLE_TIMESTAMP_RELATIVE,
        TABLE_TIMESTAMP_LEFT,
        TABLE_TIMESTAMP_DATE,
        TABLE_TIMESPAN,
        TABLE_TIMESPAN_MSEC,
        TABLE_TIMESPAN_DAY,
        TABLE_SIZE,
        TABLE_BPS,
        TABLE_INT,
        TABLE_INT8,
        TABLE_INT16,
        TABLE_INT32,
        TABLE_INT64,
        TABLE_UINT,
        TABLE_UINT8,
        TABLE_UINT16,
        TABLE_UINT32,
        TABLE_UINT64,
        TABLE_UINT64_HEX,
        TABLE_PERCENT,
        TABLE_IFINDEX,
        TABLE_IN_ADDR,  /* Takes a union in_addr_union (or a struct in_addr) */
        TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */
        TABLE_ID128,
        TABLE_UUID,
        TABLE_UID,
        TABLE_GID,
        TABLE_PID,
        TABLE_SIGNAL,
        TABLE_MODE,            /* as in UNIX file mode (mode_t), in typical octal output */
        TABLE_MODE_INODE_TYPE, /* also mode_t, but displays only the inode type as string */
        TABLE_DEVNUM,          /* a dev_t, displayed in the usual major:minor way */
        _TABLE_DATA_TYPE_MAX,

        /* The following are not really data types, but commands for table_add_cell_many() to make changes to
         * a cell just added. */
        TABLE_SET_MINIMUM_WIDTH,
        TABLE_SET_MAXIMUM_WIDTH,
        TABLE_SET_WEIGHT,
        TABLE_SET_ALIGN_PERCENT,
        TABLE_SET_ELLIPSIZE_PERCENT,
        TABLE_SET_COLOR,
        TABLE_SET_RGAP_COLOR,
        TABLE_SET_BOTH_COLORS,
        TABLE_SET_URL,
        TABLE_SET_UPPERCASE,

        _TABLE_DATA_TYPE_INVALID = -EINVAL,
} TableDataType;

typedef enum TableErsatz {
        TABLE_ERSATZ_EMPTY,
        TABLE_ERSATZ_DASH,
        TABLE_ERSATZ_UNSET,
        TABLE_ERSATZ_NA,
        _TABLE_ERSATZ_MAX,
} TableErsatz;

typedef struct Table Table;
typedef struct TableCell TableCell;

Table *table_new_internal(const char *first_header, ...) _sentinel_;
#define table_new(...) table_new_internal(__VA_ARGS__, NULL)
Table *table_new_raw(size_t n_columns);
Table *table_new_vertical(void);
Table *table_unref(Table *t);

DEFINE_TRIVIAL_CLEANUP_FUNC(Table*, table_unref);

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);
static inline int table_add_cell(Table *t, TableCell **ret_cell, TableDataType type, const void *data) {
        return table_add_cell_full(t, ret_cell, type, data, SIZE_MAX, SIZE_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
}
int table_add_cell_stringf_full(Table *t, TableCell **ret_cell, TableDataType type, const char *format, ...) _printf_(4, 5);
#define table_add_cell_stringf(t, ret_cell, format, ...) table_add_cell_stringf_full(t, ret_cell, TABLE_STRING, format, __VA_ARGS__)

int table_fill_empty(Table *t, size_t until_column);

int table_dup_cell(Table *t, TableCell *cell);

int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width);
int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width);
int table_set_weight(Table *t, TableCell *cell, unsigned weight);
int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
int table_set_color(Table *t, TableCell *cell, const char *color);
int table_set_rgap_color(Table *t, TableCell *cell, const char *color);
int table_set_url(Table *t, TableCell *cell, const char *url);
int table_set_uppercase(Table *t, TableCell *cell, bool b);

int table_update(Table *t, TableCell *cell, TableDataType type, const void *data);

int table_add_many_internal(Table *t, TableDataType first_type, ...);
#define table_add_many(t, ...) table_add_many_internal(t, __VA_ARGS__, _TABLE_DATA_TYPE_MAX)

void table_set_header(Table *table, bool b);
void table_set_width(Table *t, size_t width);
void table_set_cell_height_max(Table *t, size_t height);
void table_set_ersatz_string(Table *t, TableErsatz ersatz);
int table_set_display_internal(Table *t, size_t first_column, ...);
#define table_set_display(...) table_set_display_internal(__VA_ARGS__, SIZE_MAX)
int table_set_sort_internal(Table *t, size_t first_column, ...);
#define table_set_sort(...) table_set_sort_internal(__VA_ARGS__, SIZE_MAX)
int table_set_reverse(Table *t, size_t column, bool b);
int table_hide_column_from_display_internal(Table *t, ...);
#define table_hide_column_from_display(t, ...) table_hide_column_from_display_internal(t, __VA_ARGS__, (size_t) -1)

int table_print(Table *t, FILE *f);
int table_format(Table *t, char **ret);

static inline TableCell* TABLE_HEADER_CELL(size_t i) {
        return SIZE_TO_PTR(i + 1);
}

size_t table_get_rows(Table *t);
size_t table_get_columns(Table *t);

TableCell *table_get_cell(Table *t, size_t row, size_t column);

const void *table_get(Table *t, TableCell *cell);
const void *table_get_at(Table *t, size_t row, size_t column);

int table_to_json(Table *t, JsonVariant **ret);
int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags);

int table_print_with_pager(Table *t, JsonFormatFlags json_format_flags, PagerFlags pager_flags, bool show_header);

int table_set_json_field_name(Table *t, size_t idx, const char *name);

#define table_log_add_error(r) \
        log_error_errno(r, "Failed to add cells to table: %m")

#define table_log_print_error(r) \
        log_error_errno(r, "Failed to print table: %m")

#define table_log_sort_error(r) \
        log_error_errno(r, "Failed to sort table: %m")