static void do_print1(struct table *test_tbl)
{
table_col_str(test_tbl, test_col0_str, "sdsdf");
- table_append_str(test_tbl, "aaaaa");
table_col_int(test_tbl, test_col1_int, -10);
table_col_int(test_tbl, test_col1_int, 10000);
table_col_uint(test_tbl, test_col2_uint, 10);
table_end_row(test_tbl);
table_col_str(test_tbl, test_col0_str, "test");
- table_append_str(test_tbl, "bbbbb");
table_col_int(test_tbl, test_col1_int, -100);
table_col_uint(test_tbl, test_col2_uint, 100);
table_col_bool(test_tbl, test_col3_bool, 0);
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str
Out <<EOF
col3_bool col0_str
- true sdsdf,aaaaa
- false test,bbbbb
+ true sdsdf
+ false test
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str
Out <<EOF
col3_bool col0_str
- true sdsdf,aaaaa
- false test,bbbbb
+ true sdsdf
+ false test
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double
Out <<EOF
col3_bool col0_str col4_double
- true sdsdf,aaaaa 1.50
- false test,bbbbb 1.50
+ true sdsdf 1.50
+ false test 1.50
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double -T 'col-delim:;' -T fmt:machine
Out <<EOF
col3_bool;col0_str;col4_double
-true;sdsdf,aaaaa;1.50
-false;test,bbbbb;1.50
+true;sdsdf;1.50
+false;test;1.50
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double -T 'col-delim:;' -T fmt:machine -T header:1
Out <<EOF
col3_bool;col0_str;col4_double
-true;sdsdf,aaaaa;1.50
-false;test,bbbbb;1.50
+true;sdsdf;1.50
+false;test;1.50
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double -T 'col-delim:;' -T fmt:machine -T header:0
Out <<EOF
-true;sdsdf,aaaaa;1.50
-false;test,bbbbb;1.50
+true;sdsdf;1.50
+false;test;1.50
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double -T 'col-delim:;' -T fmt:machine -T noheader
Out <<EOF
-true;sdsdf,aaaaa;1.50
-false;test,bbbbb;1.50
+true;sdsdf;1.50
+false;test;1.50
EOF
Run: ../obj/ucw/table-test -T cols:col3_bool,col0_str,col4_double -T 'col-delim:AHOJ' -T fmt:machine -T noheader
Out <<EOF
-trueAHOJsdsdf,aaaaaAHOJ1.50
-falseAHOJtest,bbbbbAHOJ1.50
+trueAHOJsdsdfAHOJ1.50
+falseAHOJtestAHOJ1.50
EOF
Run: ../obj/ucw/table-test -T 'cols:*' -T fmt:blockline
Out <<EOF
-col0_str: sdsdf,aaaaa
+col0_str: sdsdf
col1_int: 10000
col2_uint: XXX-22222
col3_bool: true
col4_double: 1.50
-col0_str: test,bbbbb
+col0_str: test
col1_int: -100
col2_uint: 100
col3_bool: false
#include <time.h>
#include <stdio.h>
-void table_col_name(struct table *tbl, const char *col_name, u64 val)
+void table_col_size_name(struct table *tbl, const char *col_name, u64 val)
{
+ int col = table_get_col_idx(tbl, col_name);
+ table_col_size(tbl, col, val);
}
void table_col_size(struct table *tbl, int col, u64 val)
// FIXME: do some rounding?
val = val / unit_div[tbl->column_order[col].output_type];
- tbl->col_str_ptrs[col] = mp_printf(tbl->pool, "%lu%s", val, unit_suffix[tbl->column_order[col].output_type]);
+ //tbl->col_str_ptrs[col] = mp_printf(tbl->pool, "%lu%s", val, unit_suffix[tbl->column_order[col].output_type]);
+ table_col_printf(tbl, col, "%lu%s", val, unit_suffix[tbl->column_order[col].output_type]);
}
#define FORMAT_TIME_SIZE 20 // Minimum buffer size
+void table_col_timestamp_name(struct table *tbl, const char * col_name, u64 val)
+{
+ int col = table_get_col_idx(tbl, col_name);
+ table_col_size(tbl, col, val);
+}
+
void table_col_timestamp(struct table *tbl, int col, u64 val)
{
ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
break;
}
- tbl->col_str_ptrs[col] = mp_printf(tbl->pool, "%s", formatted_time_buf);
+ //tbl->col_str_ptrs[col] = mp_printf(tbl->pool, "%s", formatted_time_buf);
+ table_col_printf(tbl, col, "%s", formatted_time_buf);
}
#undef TABLE_COL_PROTO
*/
+void table_col_size_name(struct table *tbl, const char *col_name, u64 val);
+void table_col_timestamp_name(struct table *tbl, const char * col_name, u64 val);
+
void table_col_size(struct table *tbl, int col, u64 val);
void table_col_timestamp(struct table *tbl, int col, u64 val);
#include <ucw/table.h>
#include <stdlib.h>
+#include <stdio.h>
+
+/* Forward declarations */
+
+static void table_update_ll(struct table *tbl);
/*** Management of tables ***/
ASSERT(tbl->columns[col_count].name != NULL);
ASSERT(tbl->columns[col_count].type == COL_TYPE_ANY || tbl->columns[col_count].fmt != NULL);
ASSERT(tbl->columns[col_count].width != 0);
+
col_count++;
}
tbl->pool = mp_new(4096);
ASSERT_MSG(tbl->out, "Output fastbuf not specified.");
- if(!tbl->col_str_ptrs) {
- tbl->col_str_ptrs = mp_alloc_zero(tbl->pool, sizeof(char *) * tbl->column_count);
- }
-
if(tbl->column_order == NULL) table_make_default_column_order(tbl);
-
+ else {
+ // update linked lists in case that the lists were initialized in static parts
+ table_update_ll(tbl);
+ }
if(tbl->formatter->table_start != NULL) tbl->formatter->table_start(tbl);
mp_save(tbl->pool, &tbl->pool_state);
ASSERT_MSG(tbl->col_delimiter, "In-between column delimiter not specified.");
- ASSERT_MSG(tbl->append_delimiter, "Append delimiter not specified.");
}
void table_end(struct table *tbl)
return tmp;
}
+
+static void table_update_ll(struct table *tbl)
+{
+ int cols_to_output = tbl->cols_to_output;
+
+ for(int i = 0; i < tbl->column_count; i++) {
+ tbl->columns[i].first_column = -1;
+ tbl->columns[i].last_column = -1;
+ }
+
+ for(int i = 0; i < cols_to_output; i++) {
+ //int col_idx = col_order[i];
+ //tbl->column_order[i].idx = col_idx;
+ //tbl->column_order[i].cell_content = NULL;
+ int col_idx = tbl->column_order[i].idx;//col_order[i];
+ int last = tbl->columns[col_idx].last_column;
+ if(last != -1) {
+ tbl->columns[col_idx].last_column = i;
+ tbl->column_order[last].next_column = i;
+ } else {
+ tbl->columns[col_idx].last_column = i;
+ tbl->columns[col_idx].first_column = i;
+ }
+ tbl->column_order[i].next_column = -1;
+ }
+}
+
void table_set_col_order(struct table *tbl, int *col_order, int cols_to_output)
{
for(int i = 0; i < cols_to_output; i++) {
tbl->cols_to_output = cols_to_output;
tbl->column_order = mp_alloc_zero(tbl->pool, sizeof(struct table_col_info) * cols_to_output);
for(int i = 0; i < cols_to_output; i++) {
- tbl->column_order[i].idx = col_order[i];
+ int col_idx = col_order[i];
+ tbl->column_order[i].idx = col_idx;
+ tbl->column_order[i].cell_content = NULL;
}
+ table_update_ll(tbl);
}
-
bool table_col_is_printed(struct table *tbl, uint col_idx)
{
- for(uint i = 0; i < tbl->cols_to_output; i++) {
- if(tbl->column_order[i].idx == col_idx) return 1;
- }
+ if(tbl->columns[col_idx].first_column == -1) return 0;
- return 0;
+ return 1;
}
/**
const char * table_set_col_order_by_name(struct table *tbl, const char *col_order_str)
{
if(col_order_str[0] == '*') {
- tbl->column_order = mp_alloc(tbl->pool, sizeof(struct table_col_info) * tbl->column_count);
- tbl->cols_to_output = tbl->column_count;
- for(uint i = 0; i < tbl->cols_to_output; i++) {
- tbl->column_order[i].idx = i;
- tbl->column_order[i].output_type = 0;
+ int *col_order_int = alloca(sizeof(int) * tbl->column_count);
+ for(int i = 0; i < tbl->column_count; i++) {
+ col_order_int[i] = i;
}
+ table_set_col_order(tbl, col_order_int, tbl->column_count);
return NULL;
}
}
}
- int *col_order_int = alloca(sizeof(int) * col_count); //mp_alloc_zero(tbl->pool, sizeof(int) * col_count);
+ int *col_order_int = alloca(sizeof(int) * col_count);
int curr_col_order_int = 0;
const char *name_start = tmp_col_order;
while(name_start) {
name_start = next;
}
- //tbl->column_order = col_order_int;
- //tbl->cols_to_output = curr_col_order_int;
table_set_col_order(tbl, col_order_int, curr_col_order_int);
return NULL;
}
/*** Table cells ***/
+static void table_set_all_cols_content(struct table *tbl, int col, char *col_content, int override)
+{
+ int curr_col = tbl->columns[col].first_column;
+ while(curr_col != -1) {
+ //fprintf(stdout, "curr_col: %d\n", curr_col);
+ //fflush(stdout);
+ if(override == 0 && tbl->column_order[curr_col].output_type != 0) {
+ die("Error while setting content of all cells of a single type column, cell format should not be overriden.");
+ }
+ tbl->column_order[curr_col].cell_content = col_content;
+ curr_col = tbl->column_order[curr_col].next_column;
+ }
+}
+
void table_col_printf(struct table *tbl, int col, const char *fmt, ...)
{
ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
tbl->row_printing_started = 1;
va_list args;
va_start(args, fmt);
- tbl->col_str_ptrs[col] = mp_vprintf(tbl->pool, fmt, args);
+ char *cell_content = mp_vprintf(tbl->pool, fmt, args);
+ table_set_all_cols_content(tbl, col, cell_content, 1);
va_end(args);
}
[COL_TYPE_LAST] = NULL
};
-#define TABLE_COL(_name_, _type_, _typeconst_) void table_col_##_name_(struct table *tbl, int col, _type_ val) \
+#define TABLE_COL(_name_, _type_, _typeconst_) void table_col_##_name_(struct table *tbl, int col, _type_ val)\
{\
const char *fmt = tbl->columns[col].fmt;\
if(tbl->columns[col].type == COL_TYPE_ANY) {\
table_col_##_name_##_fmt(tbl, col, fmt, val);\
}
-#define TABLE_COL_STR(_name_, _type_, _typeconst_) void table_col_##_name_##_name(struct table *tbl, const char *col_name, _type_ val) \
+#define TABLE_COL_STR(_name_, _type_, _typeconst_) void table_col_##_name_##_name(struct table *tbl, const char *col_name, _type_ val)\
{\
int col = table_get_col_idx(tbl, col_name);\
table_col_##_name_(tbl, col, val);\
}
-#define TABLE_COL_FMT(_name_, _type_, _typeconst_) void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val)\
+#define TABLE_COL_FMT(_name_, _type_, _typeconst_) void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val UNUSED)\
{\
ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);\
ASSERT(tbl->columns[col].type == COL_TYPE_ANY || _typeconst_ == tbl->columns[col].type);\
ASSERT(fmt != NULL);\
tbl->last_printed_col = col;\
tbl->row_printing_started = 1;\
- tbl->col_str_ptrs[col] = mp_printf(tbl->pool, fmt, val);\
+ char *cell_content = mp_printf(tbl->pool, fmt, val);\
+ table_set_all_cols_content(tbl, col, cell_content, 0);\
}
#define TABLE_COL_BODIES(_name_, _type_, _typeconst_) TABLE_COL(_name_, _type_, _typeconst_);\
tbl->last_printed_col = col;
tbl->row_printing_started = 1;
- tbl->col_str_ptrs[col] = mp_printf(tbl->pool, fmt, val ? "true" : "false");
-}
-#define TABLE_APPEND(_name_, _type_, _typeconst_) void table_append_##_name_(struct table *tbl, _type_ val) \
- {\
- ASSERT(tbl->last_printed_col != -1 || tbl->row_printing_started != 0);\
- ASSERT(_typeconst_ == tbl->columns[tbl->last_printed_col].type);\
- int col = tbl->last_printed_col;\
- mp_printf_append(tbl->pool, tbl->col_str_ptrs[col], "%s", tbl->append_delimiter);\
- tbl->col_str_ptrs[col] = mp_printf_append(tbl->pool, tbl->col_str_ptrs[col], tbl->columns[col].fmt, val);\
+ int curr_col = tbl->columns[col].first_column;
+ while(curr_col != -1) {
+ switch(tbl->column_order[curr_col].output_type) {
+ case CELL_OUT_HUMAN_READABLE:
+ tbl->column_order[curr_col].cell_content = mp_printf(tbl->pool, fmt, val ? "true" : "false");
+ break;
+ case CELL_OUT_MACHINE_READABLE:
+ // FIXME: this is just an example of printing in different formats
+ tbl->column_order[curr_col].cell_content = mp_printf(tbl->pool, fmt, val ? "1" : "0");
+ break;
+ default:
+ die("Unsupported output type.");
+ }
+ curr_col = tbl->column_order[curr_col].next_column;
}
-TABLE_APPEND(int, int, COL_TYPE_INT)
-TABLE_APPEND(uint, uint, COL_TYPE_UINT)
-TABLE_APPEND(double, double, COL_TYPE_DOUBLE)
-TABLE_APPEND(str, const char *, COL_TYPE_STR)
-TABLE_APPEND(intmax, intmax_t, COL_TYPE_INTMAX)
-TABLE_APPEND(uintmax, uintmax_t, COL_TYPE_UINTMAX)
-TABLE_APPEND(u64, u64, COL_TYPE_U64)
-#undef TABLE_APPEND
-
-void table_append_bool(struct table *tbl, int val)
-{
- ASSERT(tbl->last_printed_col != -1 || tbl->row_printing_started != 0);
- ASSERT(COL_TYPE_BOOL == tbl->columns[tbl->last_printed_col].type);
-
- int col = tbl->last_printed_col;
-
- mp_printf_append(tbl->pool, tbl->col_str_ptrs[col], "%s", tbl->append_delimiter);
-
- tbl->col_str_ptrs[col] = mp_printf_append(tbl->pool, tbl->col_str_ptrs[col], tbl->columns[col].fmt, val ? "true" : "false");
-}
-
-void table_append_printf(struct table *tbl, const char *fmt, ...)
-{
- ASSERT(tbl->last_printed_col != -1 || tbl->row_printing_started != 0);
- int col = tbl->last_printed_col;
-
- va_list args;
- va_start(args, fmt);
-
- mp_printf_append(tbl->pool, tbl->col_str_ptrs[col], "%s", tbl->append_delimiter);
- tbl->col_str_ptrs[col] = mp_vprintf_append(tbl->pool, tbl->col_str_ptrs[col], fmt, args);
-
- va_end(args);
+ // FIXME: add to printing of all columns
}
void table_reset_row(struct table *tbl)
{
- memset(tbl->col_str_ptrs, 0, sizeof(char *) * tbl->column_count);
+ for(uint i = 0; i < tbl->cols_to_output; i++) {
+ tbl->column_order[i].cell_content = NULL;
+ }
mp_restore(tbl->pool, &tbl->pool_state);
tbl->last_printed_col = -1;
tbl->row_printing_started = 0;
void table_col_fbend(struct table *tbl)
{
- tbl->col_str_ptrs[tbl->col_out] = fbpool_end(&tbl->fb_col_out);
+ char *cell_content = fbpool_end(&tbl->fb_col_out);
+ table_set_all_cols_content(tbl, tbl->col_out, cell_content, 1);
tbl->col_out = -1;
}
}
int col_width = tbl->columns[col_idx].width & CELL_WIDTH_MASK;
if(tbl->columns[col_idx].width & CELL_ALIGN_LEFT) col_width = -1 * col_width;
- bprintf(tbl->out, "%*s", col_width, tbl->col_str_ptrs[col_idx]);
+ bprintf(tbl->out, "%*s", col_width, tbl->column_order[i].cell_content);
}
bputc(tbl->out, '\n');
}
tbl->col_delimiter = " ";
}
- if(tbl->append_delimiter == NULL) {
- tbl->append_delimiter = ",";
- }
-
if(tbl->print_header != 0) {
table_write_header(tbl);
}
static void table_row_machine_readable(struct table *tbl)
{
for(uint i = 0; i < tbl->cols_to_output; i++) {
- int col_idx = tbl->column_order[i].idx;
+ //int col_idx = tbl->column_order[i].idx;
if(i) {
bputs(tbl->out, tbl->col_delimiter);
}
- bputs(tbl->out, tbl->col_str_ptrs[col_idx]);
+ bputs(tbl->out, tbl->column_order[i].cell_content);
}
bputc(tbl->out, '\n');
}
static void table_start_machine_readable(struct table *tbl)
{
if(tbl->col_delimiter == NULL) {
- tbl->col_delimiter = ";";
- }
-
- if(tbl->append_delimiter == NULL) {
- tbl->append_delimiter = ",";
+ tbl->col_delimiter = "\t";
}
if(tbl->print_header != 0) {
{
for(uint i = 0; i < tbl->cols_to_output; i++) {
int col_idx = tbl->column_order[i].idx;
- bprintf(tbl->out, "%s: %s\n", tbl->columns[col_idx].name, tbl->col_str_ptrs[col_idx]);
+ bprintf(tbl->out, "%s: %s\n", tbl->columns[col_idx].name, tbl->column_order[i].cell_content);
}
bputc(tbl->out, '\n');
}
static void table_start_blockline(struct table *tbl)
{
if(tbl->col_delimiter == NULL) {
- tbl->col_delimiter = " ";
- }
-
- if(tbl->append_delimiter == NULL) {
- tbl->append_delimiter = ",";
+ tbl->col_delimiter = "\n";
}
}
TBL_COL_ORDER(test_column_order),
TBL_OUTPUT_HUMAN_READABLE,
TBL_COL_DELIMITER("\t"),
- TBL_APPEND_DELIMITER(",")
};
/**
static void do_print1(struct table *test_tbl)
{
table_col_str(test_tbl, test_col0_str, "sdsdf");
- table_append_str(test_tbl, "aaaaa");
table_col_int(test_tbl, test_col1_int, -10);
table_col_int(test_tbl, test_col1_int, 10000);
table_col_uint(test_tbl, test_col2_uint, 10);
table_end_row(test_tbl);
table_col_str(test_tbl, test_col0_str, "test");
- table_append_str(test_tbl, "bbbbb");
table_col_int(test_tbl, test_col1_int, -100);
table_col_uint(test_tbl, test_col2_uint, 100);
table_col_bool(test_tbl, test_col3_bool, 0);
TBL_COL_ORDER(test_any_column_order),
TBL_OUTPUT_HUMAN_READABLE,
TBL_COL_DELIMITER("\t"),
- TBL_APPEND_DELIMITER(",")
};
static void test_any_type(struct fastbuf *out)
table_end_row(&test_any_tbl);
table_col_printf(&test_any_tbl, test_any_col0_int, "%d", 10);
- table_append_printf(&test_any_tbl, "%d", 20);
- table_append_printf(&test_any_tbl, "%d", 30);
table_col_double(&test_any_tbl, test_any_col1_any, 1.4);
- table_append_printf(&test_any_tbl, "%.2lf", 1.5);
- table_append_printf(&test_any_tbl, "%.2lf", 1.6);
table_end_row(&test_any_tbl);
table_end(&test_any_tbl);
#define CELL_FLAG_MASK (CELL_ALIGN_LEFT)
#define CELL_WIDTH_MASK (~CELL_FLAG_MASK)
+#define CELL_OUT_HUMAN_READABLE 0
+#define CELL_OUT_MACHINE_READABLE 1
+
/**
* Definition of a single table column.
* Usually, this is generated using the `TABLE_COL_`'type' macros.
int width; // [*] Width of the column (in characters) OR'ed with column flags
const char *fmt; // [*] Default format of each cell in the column
enum column_type type; // [*] Type of the cells in the column
+ int first_column;
+ int last_column;
};
struct table_col_info {
uint idx;
- uint output_type;
+ char *cell_content;
+ int next_column;
+ int output_type;
};
/**
struct mempool_state pool_state; // State of the pool after the table is initialized, i.e., before
// per-row data have been allocated.
- char **col_str_ptrs; // Values of cells in the current row (allocated from the pool)
-
struct table_col_info *column_order; // [*] Order of the columns in the print-out of the table
uint cols_to_output; // [*] Number of columns that are printed
const char *col_delimiter; // [*] Delimiter that is placed between columns
- const char *append_delimiter; // [*] Separator of multiple values in a single cell (see table_append_...())
+ //const char *append_delimiter; // [*] Separator of multiple values in a single cell (see table_append_...())
uint print_header; // [*] 0 indicates that table header should not be printed
struct fastbuf *out; // [*] Fastbuffer to which the table is printed
*
***/
-#define TBL_COL_STR(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_STR }
-#define TBL_COL_INT(_name, _width) { .name = _name, .width = _width, .fmt = "%d", .type = COL_TYPE_INT }
-#define TBL_COL_S64(_name, _width) { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_S64 }
-#define TBL_COL_UINT(_name, _width) { .name = _name, .width = _width, .fmt = "%u", .type = COL_TYPE_UINT }
-#define TBL_COL_U64(_name, _width) { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_U64 }
-#define TBL_COL_INTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%jd", .type = COL_TYPE_INTMAX }
-#define TBL_COL_UINTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%ju", .type = COL_TYPE_UINTMAX }
-#define TBL_COL_HEXUINT(_name, _width) { .name = _name, .width = _width, .fmt = "0x%x", .type = COL_TYPE_UINT }
-#define TBL_COL_DOUBLE(_name, _width, _prec) { .name = _name, .width = _width, .fmt = "%." #_prec "lf", .type = COL_TYPE_DOUBLE }
-#define TBL_COL_BOOL(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_BOOL }
-#define TBL_COL_ANY(_name, _width) { .name = _name, .width = _width, .fmt = 0, .type = COL_TYPE_ANY }
-
-#define TBL_COL_STR_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_STR }
-#define TBL_COL_INT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INT }
-#define TBL_COL_S64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_S64 }
-#define TBL_COL_UINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
-#define TBL_COL_U64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_U64 }
-#define TBL_COL_INTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INTMAX }
-#define TBL_COL_UINTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINTMAX }
-#define TBL_COL_HEXUINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT }
-#define TBL_COL_BOOL_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_BOOL }
+#define TBL_COL_LIST_INIT .first_column = -1, .last_column = -1
+#define TBL_COL_STR(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_STR, TBL_COL_LIST_INIT }
+#define TBL_COL_INT(_name, _width) { .name = _name, .width = _width, .fmt = "%d", .type = COL_TYPE_INT, TBL_COL_LIST_INIT }
+#define TBL_COL_S64(_name, _width) { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_S64, TBL_COL_LIST_INIT }
+#define TBL_COL_UINT(_name, _width) { .name = _name, .width = _width, .fmt = "%u", .type = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_U64(_name, _width) { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_U64, TBL_COL_LIST_INIT }
+#define TBL_COL_INTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%jd", .type = COL_TYPE_INTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_UINTMAX(_name, _width) { .name = _name, .width = _width, .fmt = "%ju", .type = COL_TYPE_UINTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_HEXUINT(_name, _width) { .name = _name, .width = _width, .fmt = "0x%x", .type = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_DOUBLE(_name, _width, _prec) { .name = _name, .width = _width, .fmt = "%." #_prec "lf", .type = COL_TYPE_DOUBLE, TBL_COL_LIST_INIT }
+#define TBL_COL_BOOL(_name, _width) { .name = _name, .width = _width, .fmt = "%s", .type = COL_TYPE_BOOL, TBL_COL_LIST_INIT }
+#define TBL_COL_ANY(_name, _width) { .name = _name, .width = _width, .fmt = 0, .type = COL_TYPE_ANY, TBL_COL_LIST_INIT }
+
+#define TBL_COL_STR_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_STR, TBL_COL_LIST_INIT }
+#define TBL_COL_INT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INT, TBL_COL_LIST_INIT }
+#define TBL_COL_S64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_S64, TBL_COL_LIST_INIT }
+#define TBL_COL_UINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_U64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_U64, TBL_COL_LIST_INIT }
+#define TBL_COL_INTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_INTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_UINTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_HEXUINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_BOOL_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type = COL_TYPE_BOOL, TBL_COL_LIST_INIT }
#define TBL_COL_END { .name = 0, .width = 0, .fmt = 0, .type = COL_TYPE_LAST }
#define TBL_COLUMNS .columns = (struct table_column [])
#define TBL_COL_ORDER(order) .column_order = (struct table_col_info *) order, .cols_to_output = ARRAY_SIZE(order)
#define TBL_COL_DELIMITER(_delimiter_) .col_delimiter = _delimiter_
-#define TBL_APPEND_DELIMITER(_delimiter_) .append_delimiter = _delimiter_
-#define TBL_COL(_idx) { .idx = _idx, .output_type = 0 }
+#define TBL_COL(_idx) { .idx = _idx, .output_type = 0, .next_column = -1 }
+#define TBL_COL_FMT(_idx, _fmt) { .idx = _idx, .output_type = 0, .next_column = -1, .fmt = _fmt }
+#define TBL_COL_TYPE(_idx, _type) { .idx = _idx, .output_type = _type, .next_column = -1 }
+
#define TBL_OUTPUT_HUMAN_READABLE .formatter = &table_fmt_human_readable
#define TBL_OUTPUT_BLOCKLINE .formatter = &table_fmt_blockline
void table_col_bool_fmt(struct table *tbl, int col, const char *fmt, uint val);
#undef TABLE_COL_PROTO
-#define TABLE_APPEND_PROTO(_name_, _type_) void table_append_##_name_(struct table *tbl, _type_ val)
-TABLE_APPEND_PROTO(int, int);
-TABLE_APPEND_PROTO(uint, uint);
-TABLE_APPEND_PROTO(double, double);
-TABLE_APPEND_PROTO(str, const char *);
-TABLE_APPEND_PROTO(intmax, intmax_t);
-TABLE_APPEND_PROTO(uintmax, uintmax_t);
-TABLE_APPEND_PROTO(s64, s64);
-TABLE_APPEND_PROTO(u64, u64);
-void table_append_bool(struct table *tbl, int val);
-#undef TABLE_APPEND_PROTO
-
/**
* Set a particular cell of the current row to a string formatted
* by sprintf(). This function can set a column of an arbitrary type.
**/
void table_col_printf(struct table *tbl, int col, const char *fmt, ...) FORMAT_CHECK(printf, 3, 4);
-/**
- * Append a string formatted by sprintf() to the most recently filled cell.
- * This function can work with columns of an arbitrary type.
- **/
-void table_append_printf(struct table *tbl, const char *fmt, ...) FORMAT_CHECK(printf, 2, 3);
-
/**
* Alternatively, a string cell can be constructed as a stream.
* This function creates a fastbuf stream connected to the contents
void (*table_end)(struct table *tbl); // [*] table_end callback (optional)
bool (*process_option)(struct table *tbl, const char *key, const char *value, const char **err);
// [*] Process table option and possibly return an error message (optional)
+ const char *formats[];
};
/** Standard formatter for human-readable output. **/
true
false
col0_str col2_uint col1_int col3_bool
- sdsdf,aaaaa XXX-22222 10000 true
- test,bbbbb 100 -100 false
- sdsdf,aaaaa XXX-22222 10000 true
- test,bbbbb 100 -100 false
+ sdsdf XXX-22222 10000 true
+ test 100 -100 false
+ sdsdf XXX-22222 10000 true
+ test 100 -100 false
col3_bool
true
false
col3_bool col0_str
- true sdsdf,aaaaa
- false test,bbbbb
+ true sdsdf
+ false test
col0_str col3_bool col2_uint
- sdsdf,aaaaa true XXX-22222
- test,bbbbb false 100
+ sdsdf true XXX-22222
+ test false 100
col0_str col3_bool col2_uint col0_str col3_bool col2_uint col0_str col3_bool col2_uint
- sdsdf,aaaaa true XXX-22222 sdsdf,aaaaa true XXX-22222 sdsdf,aaaaa true XXX-22222
- test,bbbbb false 100 test,bbbbb false 100 test,bbbbb false 100
+ sdsdf true XXX-22222 sdsdf true XXX-22222 sdsdf true XXX-22222
+ test false 100 test false 100 test false 100
col0_str col1_int col2_uint col3_bool col4_double
- sdsdf,aaaaa 10000 XXX-22222 true AAA
- test,bbbbb -100 100 false 1.50
+ sdsdf 10000 XXX-22222 true AAA
+ test -100 100 false 1.50
col0_int col1_any
-10 10000
-10 1.40
-10,20,30 1.40,1.50,1.60
+ 10 1.40
EOF