static struct table_template test_tbl = {
TBL_COLUMNS {
- [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, UNIT_SIZE_BYTE),
+ [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, SIZE_UNITS_FIXED | UNIT_SIZE_BYTE),
[TEST_COL1_TS] = TBL_COL_TIMESTAMP("ts", 20),
TBL_COL_END
},
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
table_end_row(tbl);
- tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNIT_KILOBYTE;
+ tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNITS_FIXED | SIZE_UNIT_KILOBYTE;
table_col_size(tbl, TEST_COL0_SIZE, test_size);
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
table_end_row(tbl);
- tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNIT_MEGABYTE;
+ tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNITS_FIXED | SIZE_UNIT_MEGABYTE;
table_col_size(tbl, TEST_COL0_SIZE, test_size);
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
table_end_row(tbl);
- tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNIT_GIGABYTE;
+ tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNITS_FIXED | SIZE_UNIT_GIGABYTE;
tbl->column_order[TEST_COL1_TS].output_type = TIMESTAMP_DATETIME;
table_col_size(tbl, TEST_COL0_SIZE, test_size);
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
table_end_row(tbl);
test_size = test_size * 1024LU;
- tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNIT_TERABYTE;
+ tbl->column_order[TEST_COL0_SIZE].output_type = SIZE_UNITS_FIXED | SIZE_UNIT_TERABYTE;
tbl->column_order[TEST_COL1_TS].output_type = TIMESTAMP_DATETIME;
table_col_size(tbl, TEST_COL0_SIZE, test_size);
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
static struct table_template test_tbl2 = {
TBL_COLUMNS {
- [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, SIZE_UNIT_BYTE),
+ [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, SIZE_UNITS_FIXED | SIZE_UNIT_BYTE),
[TEST_COL1_TS] = TBL_COL_TIMESTAMP("ts", 20),
TBL_COL_END
},
#include <stdio.h>
#include <stdlib.h>
+const struct xtype xt_size;
+const struct xtype xt_timestamp;
+
static const char *unit_suffix[] = {
[SIZE_UNIT_BYTE] = "",
[SIZE_UNIT_KILOBYTE] = "KB",
[SIZE_UNIT_TERABYTE] = "TB"
};
-static bool table_set_col_opt_size(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err)
+bool table_set_col_opt_size(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err)
{
struct table_column *col_def = tbl->column_order[col_inst_idx].col_def;
- if(col_def->type != COL_TYPE_SIZE) {
+ if(col_def->type_def != COL_TYPE_SIZE) {
*err = NULL;
return false;
}
if(col_arg == NULL || strcasecmp(col_arg, "b") == 0 || strcasecmp(col_arg, "bytes") == 0) {
- tbl->column_order[col_inst_idx].output_type = SIZE_UNIT_BYTE;
+ tbl->column_order[col_inst_idx].output_type = SIZE_UNIT_BYTE | SIZE_UNITS_FIXED;
*err = NULL;
return true;
}
- tbl->column_order[col_inst_idx].output_type = CELL_OUT_UNINITIALIZED;
+ tbl->column_order[col_inst_idx].output_type = XTYPE_FMT_DEFAULT; // CELL_OUT_UNINITIALIZED;
for(uint i = SIZE_UNIT_BYTE; i <= SIZE_UNIT_TERABYTE; i++) {
if(strcasecmp(col_arg, unit_suffix[i]) == 0) {
- tbl->column_order[col_inst_idx].output_type = i;
+ tbl->column_order[col_inst_idx].output_type = i | SIZE_UNITS_FIXED;
}
}
- if(tbl->column_order[col_inst_idx].output_type == CELL_OUT_UNINITIALIZED) {
+ if(tbl->column_order[col_inst_idx].output_type == XTYPE_FMT_DEFAULT) {
*err = mp_printf(tbl->pool, "Invalid column format option: '%s' for column %d (counted from 0)", col_arg, col_inst_idx);
return true;
}
return true;
}
-struct table_user_type table_type_size = {
- .set_col_instance_option = table_set_col_opt_size,
- .type = COL_TYPE_SIZE,
-};
-
-static bool table_set_col_opt_timestamp(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err)
+bool table_set_col_opt_timestamp(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err)
{
int col_type_idx = tbl->column_order[col_inst_idx].idx;
- if(tbl->columns[col_type_idx].type != COL_TYPE_TIMESTAMP) {
+ if(tbl->columns[col_type_idx].type_def != COL_TYPE_TIMESTAMP) {
*err = NULL;
return false;
}
return true;
}
-struct table_user_type table_type_timestamp = {
- .set_col_instance_option = table_set_col_opt_timestamp,
- .type = COL_TYPE_TIMESTAMP,
-};
-
void table_col_size_name(struct table *tbl, const char *col_name, u64 val)
{
int col = table_get_col_idx(tbl, col_name);
void table_col_size(struct table *tbl, int col, u64 val)
{
ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
- ASSERT(tbl->columns[col].type == COL_TYPE_ANY || COL_TYPE_SIZE == tbl->columns[col].type);
+ ASSERT(tbl->columns[col].type_def == COL_TYPE_ANY || COL_TYPE_SIZE == tbl->columns[col].type_def);
tbl->last_printed_col = col;
tbl->row_printing_started = 1;
// FIXME: do some rounding? Or maybe use double and floating-point printing?
uint out_type = 0;
u64 curr_val = val;
- if(curr_col->output_type == CELL_OUT_UNINITIALIZED) {
+
+ if(curr_col->output_type == XTYPE_FMT_DEFAULT || curr_col->output_type == XTYPE_FMT_RAW) {
curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
out_type = SIZE_UNIT_BYTE;
- } else {
- curr_val = curr_val / unit_div[curr_col->output_type];
- out_type = curr_col->output_type;
+ } else if(curr_col->output_type == XTYPE_FMT_PRETTY) {
+ curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
+ out_type = SIZE_UNIT_BYTE; // curr_col->output_type;
+ } else if((curr_col->output_type & SIZE_UNITS_FIXED) != 0) {
+ curr_val = curr_val / unit_div[curr_col->output_type & ~SIZE_UNITS_FIXED];
+ out_type = curr_col->output_type & ~SIZE_UNITS_FIXED;
}
curr_col->cell_content = mp_printf(tbl->pool, "%lu%s", curr_val, unit_suffix[out_type]);
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);
- ASSERT(tbl->columns[col].type == COL_TYPE_ANY || COL_TYPE_TIMESTAMP == tbl->columns[col].type);
+ ASSERT(tbl->columns[col].type_def == COL_TYPE_ANY || COL_TYPE_TIMESTAMP == tbl->columns[col].type_def);
char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 };
struct tm t = *gmtime(&tmp_time);
TBL_COL_ITER_START(tbl, col, curr_col, curr_col_idx) {
switch (curr_col->output_type) {
- case TIMESTAMP_EPOCH:
- case CELL_OUT_UNINITIALIZED:
+ case XTYPE_FMT_DEFAULT:
+ case XTYPE_FMT_RAW:
sprintf(formatted_time_buf, "%lu", val);
break;
- case TIMESTAMP_DATETIME:
+ case XTYPE_FMT_PRETTY:
strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t);
break;
default:
#include <ucw/table.h>
enum size_units {
- SIZE_UNIT_BYTE = CELL_OUT_USER_DEF_START,
+ SIZE_UNIT_BYTE,
SIZE_UNIT_KILOBYTE,
SIZE_UNIT_MEGABYTE,
SIZE_UNIT_GIGABYTE,
SIZE_UNIT_AUTO
};
-enum timestamp_format {
- TIMESTAMP_EPOCH,
- TIMESTAMP_DATETIME
-};
+#define COL_TYPE_SIZE &xt_size
+#define COL_TYPE_TIMESTAMP &xt_timestamp
+
+#define TIMESTAMP_EPOCH XTYPE_FMT_RAW
+#define TIMESTAMP_DATETIME XTYPE_FMT_PRETTY
+
+#define SIZE_UNITS_FIXED 0x40000000
-#define COL_TYPE_SIZE COL_TYPE_UCW
-#define COL_TYPE_TIMESTAMP (COL_TYPE_UCW+1)
+extern const struct xtype xt_size;
+extern const struct xtype xt_timestamp;
-extern struct table_user_type table_type_timestamp;
-extern struct table_user_type table_type_size;
+bool table_set_col_opt_size(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err);
+bool table_set_col_opt_timestamp(struct table *tbl, uint col_inst_idx, const char *col_arg, char **err);
-#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_SIZE, .type_def = &table_type_size }
-#define TBL_COL_TIMESTAMP(_name, _width) { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_TIMESTAMP, .type_def = &table_type_timestamp }
+#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_SIZE, .set_col_instance_option = table_set_col_opt_size }
+#define TBL_COL_TIMESTAMP(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_TIMESTAMP, .set_col_instance_option = table_set_col_opt_timestamp }
-#define TBL_COL_SIZE_FMT(_name, _width, _units) { .name = _name, .width = _width, .fmt = "%llu", .type = COL_TYPE_SIZE, .type_def = &table_type_size }
-#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = "%lld", .type = COL_TYPE_TIMESTAMP, .type_def = &table_type_timestamp }
+#define TBL_COL_SIZE_FMT(_name, _width, _units) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_SIZE, .set_col_instance_option = table_set_col_opt_size }
+#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_TIMESTAMP, .set_col_instance_option = table_set_col_opt_timestamp }
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);
static struct table *table_make_instance(const struct table_template *tbl_template)
{
- struct table *new_inst = xmalloc_zero(sizeof(struct table)); // FIXME: update allocation to the weird schema made by pchar and mj?
+ struct mempool *pool = mp_new(4096);
+ struct table *new_inst = mp_alloc_zero(pool, sizeof(struct table)); // FIXME: update allocation to the weird schema made by pchar and mj?
new_inst->pool = mp_new(4096);
int col_count = 0; // count the number of columns in the struct table
for(;;) {
if(tbl_template->columns[col_count].name == NULL &&
- tbl_template->columns[col_count].fmt == NULL &&
tbl_template->columns[col_count].width == 0 &&
- tbl_template->columns[col_count].type == COL_TYPE_LAST)
+ tbl_template->columns[col_count].type_def == COL_TYPE_ANY)
break;
ASSERT(tbl_template->columns[col_count].name != NULL);
- ASSERT(tbl_template->columns[col_count].type == COL_TYPE_ANY || tbl_template->columns[col_count].fmt != NULL);
ASSERT(tbl_template->columns[col_count].width != 0);
col_count++;
memcpy(new_inst->column_order, tbl_template->column_order, sizeof(struct table_col_instance) * tbl_template->cols_to_output);
for(uint i = 0; i < new_inst->cols_to_output; i++) {
new_inst->column_order[i].cell_content = NULL;
- //new_inst->column_order[i].col_def = NULL; // FIXME: col_def should not be touched, probably ...
- int col_idx = new_inst->column_order[i].idx;//col_order[i];
+ int col_idx = new_inst->column_order[i].idx;
new_inst->column_order[i].col_def = new_inst->columns + col_idx;
new_inst->column_order[i].output_type = tbl_template->column_order[i].output_type;
}
{
mp_delete(tbl->pool);
memset(tbl, 0, sizeof(struct table));
- xfree(tbl);
}
// TODO: test default column order
tbl->column_order[i].idx = col_idx;
tbl->column_order[i].col_def = tbl->columns + col_idx;
tbl->column_order[i].cell_content = NULL;
- tbl->column_order[i].output_type = CELL_OUT_UNINITIALIZED;
+ tbl->column_order[i].output_type = XTYPE_FMT_DEFAULT;
}
table_update_ll(tbl);
}
{
struct table_column *col_def = tbl->column_order[col_idx].col_def;
- if(col_def->type == COL_TYPE_DOUBLE) {
+ if(col_def->type_def == COL_TYPE_DOUBLE) {
uint precision = 0;
const char *tmp_err = str_to_uint(&precision, col_arg, NULL, 0);
if(tmp_err) {
*err = mp_printf(tbl->pool, "An error occured while parsing precision: %s", tmp_err);
return false;
}
- tbl->column_order[col_idx].output_type = precision;
+ tbl->column_order[col_idx].output_type = precision; // FIXME: shift the value of precision
return true;
}
tbl->column_order[curr_col_idx].col_def = tbl->columns + col_idx;
tbl->column_order[curr_col_idx].idx = col_idx;
tbl->column_order[curr_col_idx].cell_content = NULL;
- tbl->column_order[curr_col_idx].output_type = CELL_OUT_UNINITIALIZED;
- if(tbl->columns[col_idx].type_def && tbl->columns[col_idx].type_def->set_col_instance_option) {
+ tbl->column_order[curr_col_idx].output_type = XTYPE_FMT_DEFAULT;
+ if(tbl->columns[col_idx].type_def && tbl->columns[col_idx].set_col_instance_option) {
char *err = NULL;
- tbl->columns[col_idx].type_def->set_col_instance_option(tbl, curr_col_idx, arg, &err);
+ tbl->columns[col_idx].set_col_instance_option(tbl, curr_col_idx, arg, &err);
if(err) return mp_printf(tbl->pool, "Error occured while setting column option: %s.", err);
}
/*** Table cells ***/
-static void table_set_all_inst_content(struct table *tbl, int col_templ, char *col_content, int override)
+static void table_set_all_inst_content(struct table *tbl, int col_templ, const char *col_content)
{
TBL_COL_ITER_START(tbl, col_templ, curr_col_ptr, curr_col) {
- if(override == 0 && curr_col_ptr->output_type != CELL_OUT_UNINITIALIZED ) {
- die("Error while setting content of all cells of a single type column, cell format should not be overriden.");
- }
+ //if( override == 0 ) {
+ //die("Error while setting content of all cells of a single type column, cell format should not be overriden.");
+ //}
curr_col_ptr->cell_content = col_content;
} TBL_COL_ITER_END
}
va_list args;
va_start(args, fmt);
char *cell_content = mp_vprintf(tbl->pool, fmt, args);
- table_set_all_inst_content(tbl, col, cell_content, 1);
+ table_set_all_inst_content(tbl, col, cell_content);
va_end(args);
}
-static const char *table_col_default_fmts[] = {
- [COL_TYPE_STR] = "%s",
- [COL_TYPE_INT] = "%d",
- [COL_TYPE_S64] = "%lld",
- [COL_TYPE_INTMAX] = "%jd",
- [COL_TYPE_UINT] = "%u",
- [COL_TYPE_U64] = "%llu",
- [COL_TYPE_UINTMAX] = "%ju",
- [COL_TYPE_BOOL] = "%d",
- [COL_TYPE_DOUBLE] = "%.2lf",
- [COL_TYPE_ANY] = NULL,
- [COL_TYPE_LAST] = NULL
-};
-
#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) {\
- fmt = table_col_default_fmts[_typeconst_];\
- }\
+ enum xtype_fmt fmt = tbl->columns[col].fmt;\
table_col_##_name_##_fmt(tbl, col, fmt, val);\
}
table_col_##_name_(tbl, col, val);\
}
-#define TABLE_COL_FMT(_name_, _type_, _typeconst_, _override) void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val) \
+#define TABLE_COL_FMT(_name_, _type_, _typeconst_, _override) void table_col_##_name_##_fmt(struct table *tbl, int col, enum xtype_fmt fmt, _type_ val) \
{\
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);\
+ ASSERT(tbl->columns[col].type_def == COL_TYPE_ANY || _typeconst_ == tbl->columns[col].type_def);\
tbl->last_printed_col = col;\
tbl->row_printing_started = 1;\
- char *cell_content = mp_printf(tbl->pool, fmt, val);\
- table_set_all_inst_content(tbl, col, cell_content, _override);\
+ const char *cell_content = NULL;\
+ if(tbl->columns[col].type_def != COL_TYPE_ANY) cell_content = tbl->columns[col].type_def->format(&val, fmt, tbl->pool);\
+ else cell_content = (_typeconst_)->format(&val, fmt, tbl->pool); \
+ table_set_all_inst_content(tbl, col, cell_content);\
}
#define TABLE_COL_BODIES(_name_, _type_, _typeconst_, _override) TABLE_COL(_name_, _type_, _typeconst_); \
TABLE_COL_BODIES(uintmax, uintmax_t, COL_TYPE_UINTMAX, 0)
TABLE_COL_BODIES(s64, s64, COL_TYPE_S64, 0)
TABLE_COL_BODIES(u64, u64, COL_TYPE_U64, 0)
+TABLE_COL_BODIES(double, double, COL_TYPE_DOUBLE, 0)
+//TABLE_COL_BODIES(bool, bool, COL_TYPE_BOOL, 0)
// column type double is a special case
-TABLE_COL(double, double, COL_TYPE_DOUBLE);
-TABLE_COL_STR(double, double, COL_TYPE_DOUBLE);
+//TABLE_COL(double, double, COL_TYPE_DOUBLE);
+//TABLE_COL_STR(double, double, COL_TYPE_DOUBLE);
-TABLE_COL(bool, bool, COL_TYPE_BOOL);
-TABLE_COL_STR(bool, bool, COL_TYPE_BOOL);
+TABLE_COL(bool, bool, COL_TYPE_BOOL)
+TABLE_COL_STR(bool, bool, COL_TYPE_BOOL)
+TABLE_COL_FMT(bool, bool, COL_TYPE_BOOL, 0)
#undef TABLE_COL
#undef TABLE_COL_FMT
#undef TABLE_COL_STR
#undef TABLE_COL_BODIES
-void table_col_double_fmt(struct table *tbl, int col, const char *fmt, double val)
-{
- ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
- ASSERT(tbl->columns[col].type == COL_TYPE_ANY || COL_TYPE_DOUBLE == tbl->columns[col].type);
- ASSERT(fmt != NULL);
- tbl->last_printed_col = col;
- tbl->row_printing_started = 1;
- char *cell_content = mp_printf(tbl->pool, fmt, val);
- int curr_col = tbl->columns[col].first_column;
- while(curr_col != -1) {
- char *cell_content_tmp = NULL;
- switch(tbl->column_order[curr_col].output_type) {
- case CELL_OUT_UNINITIALIZED:
- cell_content_tmp = cell_content;
- break;
- case CELL_OUT_MACHINE_READABLE:
- cell_content_tmp = mp_printf(tbl->pool, "%4lf", val);
- break;
- default:
- cell_content_tmp = mp_printf(tbl->pool, "%.*lf", tbl->column_order[curr_col].output_type, val);
- break;
- }
- tbl->column_order[curr_col].cell_content = cell_content_tmp;
- curr_col = tbl->column_order[curr_col].next_column;
- }
-}
-
-void table_col_bool_fmt(struct table *tbl, int col, const char *fmt, bool val)
-{
- ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
- ASSERT(COL_TYPE_BOOL == tbl->columns[col].type);
-
- tbl->last_printed_col = col;
- tbl->row_printing_started = 1;
-
- 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:
- case CELL_OUT_UNINITIALIZED:
- 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;
- }
-}
void table_reset_row(struct table *tbl)
{
void table_col_fbend(struct table *tbl)
{
char *cell_content = fbpool_end(&tbl->fb_col_out);
- table_set_all_inst_content(tbl, tbl->col_out, cell_content, 1);
+ table_set_all_inst_content(tbl, tbl->col_out, cell_content);
tbl->col_out = -1;
}
#include <ucw/fastbuf.h>
#include <ucw/mempool.h>
+#include <ucw/xtypes.h>
+// FIXME: update these macros
#ifdef CONFIG_UCW_CLEAN_ABI
#define table_append_bool ucw_table_append_bool
#define table_append_double ucw_table_append_double
// FIXME: update documentation according to the changes made in recent commits!
/** Types of columns. These are seldom used explicitly, using a column definition macro is preferred. **/
+
+#define COL_TYPE_STR &xt_str
+#define COL_TYPE_INT &xt_int
+#define COL_TYPE_S64 &xt_s64
+#define COL_TYPE_INTMAX &xt_intmax
+#define COL_TYPE_UINT &xt_uint
+#define COL_TYPE_U64 &xt_u64
+#define COL_TYPE_UINTMAX &xt_uintmax
+#define COL_TYPE_BOOL &xt_bool
+#define COL_TYPE_DOUBLE &xt_double
+#define COL_TYPE_ANY NULL
+
+/*
enum column_type {
COL_TYPE_STR, // String
COL_TYPE_INT, // int
COL_TYPE_ANY, // Any type
COL_TYPE_LAST
};
-
-#define COL_TYPE_UCW 0x100
-#define COL_TYPE_CUSTOM 0x1000
+*/
/** Justify cell contents to the left. **/
#define CELL_ALIGN_LEFT (1U << 31)
#define CELL_FLAG_MASK (CELL_ALIGN_LEFT)
#define CELL_WIDTH_MASK (~CELL_FLAG_MASK)
-#define CELL_OUT_UNINITIALIZED -1
-#define CELL_OUT_HUMAN_READABLE -2
-#define CELL_OUT_MACHINE_READABLE -3
-#define CELL_OUT_USER_DEF_START 5
+//#define CELL_OUT_UNINITIALIZED -1
+//#define CELL_OUT_HUMAN_READABLE -2
+//#define CELL_OUT_MACHINE_READABLE -3
+//#define CELL_OUT_USER_DEF_START 5
struct table;
-struct table_user_type {
- bool (*set_col_instance_option)(struct table *tbl, uint col, const char *value, char **err);
- // [*] process table option for a column instance
- uint type; // [*] type identifier, should be a number shifted by COL_TYPE_CUSTOM
- const char *default_fmt; // [*] default format used for printing
-};
-
/**
* Definition of a single table column.
* Usually, this is generated using the `TABLE_COL_`'type' macros.
struct table_column {
const char *name; // [*] Name of the column displayed in table header
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
+ //const char *fmt; // [*] Default format of each cell in the column
+ //enum column_type type; // [*] Type of the cells in the column
+ enum xtype_fmt fmt;
int first_column; // head of linked list of columns of this type
- struct table_user_type *type_def;
+ const struct xtype *type_def;
+
+ bool (*set_col_instance_option)(struct table *tbl, uint col, const char *value, char **err);
+ // [*] process table option for a column instance
};
// FIXME: is it correct to have idx and col_def? idx is sufficient and in fact a duplicity of idx
struct table_col_instance {
uint idx; // idx is a index into struct table::columns
struct table_column *col_def; // this is pointer to the column definition, located in the array struct table::columns
- char *cell_content; // content of the cell of the current row
+ const char *cell_content; // content of the cell of the current row
int next_column; // index of next column in linked list of columns of the same type
- int output_type; // format of this column
+ enum xtype_fmt output_type; // format of this column
};
/**
***/
#define TBL_COL_LIST_INIT .first_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_COL_STR(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_STR, TBL_COL_LIST_INIT }
+#define TBL_COL_INT(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_INT, TBL_COL_LIST_INIT }
+#define TBL_COL_S64(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_S64, TBL_COL_LIST_INIT }
+#define TBL_COL_UINT(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_U64(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_U64, TBL_COL_LIST_INIT }
+#define TBL_COL_INTMAX(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_INTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_UINTMAX(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_UINTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_HEXUINT(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_DOUBLE(_name, _width, _prec) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_DOUBLE, TBL_COL_LIST_INIT }
+#define TBL_COL_BOOL(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_BOOL, TBL_COL_LIST_INIT }
+#define TBL_COL_ANY(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = COL_TYPE_ANY, TBL_COL_LIST_INIT }
+
+#define TBL_COL_STR_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_STR, TBL_COL_LIST_INIT }
+#define TBL_COL_INT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_INT, TBL_COL_LIST_INIT }
+#define TBL_COL_S64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_S64, TBL_COL_LIST_INIT }
+#define TBL_COL_UINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_U64_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_U64, TBL_COL_LIST_INIT }
+#define TBL_COL_INTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_INTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_UINTMAX_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_UINTMAX, TBL_COL_LIST_INIT }
+#define TBL_COL_HEXUINT_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_UINT, TBL_COL_LIST_INIT }
+#define TBL_COL_BOOL_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = COL_TYPE_BOOL, TBL_COL_LIST_INIT }
+
+#define TBL_COL_END { .name = 0, .width = 0, .fmt = 0, .type_def = NULL }
#define TBL_COLUMNS .columns = (struct table_column [])
#define TBL_COL_ORDER(order) .column_order = (struct table_col_instance *) order, .cols_to_output = ARRAY_SIZE(order)
#define TBL_COL_DELIMITER(_delimiter_) .col_delimiter = _delimiter_
-#define TBL_COL(_idx) { .idx = _idx, .output_type = CELL_OUT_UNINITIALIZED, .next_column = -1 }
-#define TBL_COL_FMT(_idx, _fmt) { .idx = _idx, .output_type = CELL_OUT_UNINITIALIZED, .next_column = -1, .fmt = _fmt }
+#define TBL_COL(_idx) { .idx = _idx, .output_type = XTYPE_FMT_DEFAULT, .next_column = -1 }
+#define TBL_COL_FMT(_idx, _fmt) { .idx = _idx, .output_type = XTYPE_FMT_DEFAULT, .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 TABLE_COL_PROTO(_name_, _type_) void table_col_##_name_(struct table *tbl, int col, _type_ val);\
void table_col_##_name_##_name(struct table *tbl, const char *col_name, _type_ val);\
- void table_col_##_name_##_fmt(struct table *tbl, int col, const char *fmt, _type_ val) FORMAT_CHECK(printf, 3, 0);
+ void table_col_##_name_##_fmt(struct table *tbl, int col, enum xtype_fmt fmt, _type_ val);
// table_col_<type>_fmt has one disadvantage: it is not possible to
// check whether fmt contains format that contains formatting that is
TABLE_COL_PROTO(uintmax, uintmax_t);
TABLE_COL_PROTO(s64, s64);
TABLE_COL_PROTO(u64, u64);
+TABLE_COL_PROTO(bool, bool);
-void table_col_bool(struct table *tbl, int col, bool val);
-void table_col_bool_name(struct table *tbl, const char *col_name, bool val);
-void table_col_bool_fmt(struct table *tbl, int col, const char *fmt, bool val);
+//void table_col_bool(struct table *tbl, int col, bool val);
+//void table_col_bool_name(struct table *tbl, const char *col_name, bool val);
+//void table_col_bool_fmt(struct table *tbl, int col, enum xtype_fmt fmt, bool val);
#undef TABLE_COL_PROTO
/**
#include <ucw/mempool.h>
#include <ucw/strtonum.h>
#include <ucw/xtypes.h>
+#include <errno.h>
+#include <stdlib.h>
-static const char *xt_int_parse(const char *str, void *dest, struct mempool *pool UNUSED)
+#define XTYPE_NUM_FORMAT(_type, _fmt, _typename) static const char *xt_##_typename##_format(void *src, u32 fmt UNUSED, struct mempool *pool) \
+{\
+ return mp_printf(pool, _fmt, *(_type *)src);\
+}
+
+#define XTYPE_NUM_PARSE(_typename) static const char *xt_##_typename##_parse(const char *str, void *dest, struct mempool *pool UNUSED)\
+{\
+ return str_to_##_typename(dest, str, NULL, 10 | STN_WHOLE | STN_MINUS | STN_PLUS | STN_HEX | STN_BIN | STN_OCT);\
+}
+
+#define XTYPE_NUM_STRUCT(_type, _typename) const struct xtype xt_##_typename = {\
+ .size = sizeof(_type),\
+ .name = #_typename,\
+ .parse = xt_##_typename##_parse,\
+ .format = xt_##_typename##_format,\
+};
+
+
+#define XTYPE_NUM_DEF(_type, _fmt, _typename) XTYPE_NUM_FORMAT(_type, _fmt, _typename) \
+ XTYPE_NUM_PARSE(_typename)\
+ XTYPE_NUM_STRUCT(_type, _typename)
+
+XTYPE_NUM_DEF(int, "%d", int)
+XTYPE_NUM_DEF(s64, "%ld", s64)
+XTYPE_NUM_DEF(intmax_t, "%jd", intmax)
+XTYPE_NUM_DEF(uint, "%u", uint)
+XTYPE_NUM_DEF(u64, "%lu", u64)
+XTYPE_NUM_DEF(uintmax_t, "%ju", uintmax)
+
+/* double */
+
+static const char *xt_double_format(void *src, u32 fmt, struct mempool *pool)
+{
+ switch(fmt) {
+ case XTYPE_FMT_RAW:
+ return mp_printf(pool, "%.2lf", *(double *)src);
+ case XTYPE_FMT_PRETTY:
+ return mp_printf(pool, "%.2lf", *(double *)src);
+
+ case XTYPE_FMT_DEFAULT:
+ default:
+ return mp_printf(pool, "%.2lf", *(double *)src);
+ }
+}
+
+static const char *xt_double_parse(const char *str, void *dest, struct mempool *pool UNUSED)
+{
+ char *endptr = NULL;
+ errno = 0;
+ double result = strtod(str, &endptr);
+ size_t sz = strlen(str);
+ if(endptr != str + sz) return "Could not parse double.";
+ if(errno == ERANGE) return "Could not parse double: overflow happend during parsing";
+
+ *((double *) dest) = result;
+
+ return NULL;
+}
+
+const struct xtype xt_double = {
+ .size = sizeof(double),
+ .name = "double",
+ .parse = xt_double_parse,
+ .format = xt_double_format,
+};
+
+/* bool */
+
+static const char *xt_bool_format(void *src, u32 fmt UNUSED, struct mempool *pool) // (struct table *tbl, int col, enum xtype_fmt fmt, bool val)
+{
+ switch(fmt) {
+ case XTYPE_FMT_DEFAULT:
+ case XTYPE_FMT_PRETTY:
+ return mp_printf(pool, "%s", *((bool *)src) ? "true" : "false");
+ case XTYPE_FMT_RAW:
+ return mp_printf(pool, "%s", *((bool *)src) ? "1" : "0");
+ default:
+ die("Unsupported output type.");
+ }
+}
+
+static const char *xt_bool_parse(const char *str, void *dest, struct mempool *pool UNUSED)
+{
+ if(str[1] == 0) {
+ if(str[0] == '1') {
+ *((bool *)dest) = false;
+ return NULL;
+ }
+ if(str[0] == '1') {
+ *((bool *)dest) = true;
+ return NULL;
+ }
+ }
+
+ if(strcasecmp(str, "false") == 0) {
+ *((bool *)dest) = false;
+ return NULL;
+ }
+
+ if(strcasecmp(str, "true") == 0) {
+ *((bool *)dest) = true;
+ return NULL;
+ }
+
+ return "Could not parse bool.";
+}
+
+const struct xtype xt_bool = {
+ .size = sizeof(bool),
+ .name = "bool",
+ .parse = xt_bool_parse,
+ .format = xt_bool_format,
+};
+
+
+/* str */
+static const char *xt_str_format(void *src, u32 fmt UNUSED, struct mempool *pool) // (struct table *tbl, int col, enum xtype_fmt fmt, bool val)
{
- return str_to_int(dest, str, NULL, 10 | STN_WHOLE | STN_MINUS | STN_PLUS | STN_HEX | STN_BIN | STN_OCT);
+ return mp_printf(pool, "%s", *((char **) src));
}
-static const char *xt_int_format(void *src, u32 fmt UNUSED, struct mempool *pool)
+static const char *xt_str_parse(const char *str, void *dest, struct mempool *pool UNUSED)
{
- return mp_printf(pool, "%d", *(int *)src);
+ *((const char **) dest) = str;
+ return NULL;
}
-const struct xtype xt_int = {
- .size = sizeof(int),
- .name = "int",
- .parse = xt_int_parse,
- .format = xt_int_format,
+const struct xtype xt_str = {
+ .size = sizeof(char *),
+ .name = "str",
+ .parse = xt_str_parse,
+ .format = xt_str_format,
};
const char *xtype_format_fmt(struct xtype *xt, u32 fmt, struct mempool *pool);
// Basic set of extended types
+extern const struct xtype xt_str;
extern const struct xtype xt_int;
+extern const struct xtype xt_s64;
+extern const struct xtype xt_intmax;
+extern const struct xtype xt_uint;
+extern const struct xtype xt_u64;
+extern const struct xtype xt_uintmax;
+extern const struct xtype xt_bool;
+extern const struct xtype xt_double;
#endif