static struct table_template test_tbl = {
TBL_COLUMNS {
- [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, SIZE_UNITS_FIXED | UNIT_SIZE_BYTE),
+ [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_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].fmt = SIZE_UNITS_FIXED | SIZE_UNIT_KILOBYTE;
+ tbl->column_order[TEST_COL0_SIZE].fmt = XT_SIZE_FMT_UNIT(XT_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].fmt = SIZE_UNITS_FIXED | SIZE_UNIT_MEGABYTE;
+ tbl->column_order[TEST_COL0_SIZE].fmt = XT_SIZE_FMT_UNIT(XT_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].fmt = SIZE_UNITS_FIXED | SIZE_UNIT_GIGABYTE;
- tbl->column_order[TEST_COL1_TS].fmt = TIMESTAMP_DATETIME;
+ tbl->column_order[TEST_COL0_SIZE].fmt = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_GIGABYTE);
+ tbl->column_order[TEST_COL1_TS].fmt = XT_TIMESTAMP_FMT_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].fmt = SIZE_UNITS_FIXED | SIZE_UNIT_TERABYTE;
- tbl->column_order[TEST_COL1_TS].fmt = TIMESTAMP_DATETIME;
+ tbl->column_order[TEST_COL0_SIZE].fmt = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_TERABYTE);
+ tbl->column_order[TEST_COL1_TS].fmt = XT_TIMESTAMP_FMT_DATETIME;
table_col_size(tbl, TEST_COL0_SIZE, test_size);
table_col_timestamp(tbl, TEST_COL1_TS, test_time);
table_end_row(tbl);
static struct table_template test_tbl2 = {
TBL_COLUMNS {
- [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, SIZE_UNITS_FIXED | SIZE_UNIT_BYTE),
+ [TEST_COL0_SIZE] = TBL_COL_SIZE_FMT("size", 15, XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_BYTE)),
[TEST_COL1_TS] = TBL_COL_TIMESTAMP("ts", 20),
TBL_COL_END
},
#include <inttypes.h>
#include <errno.h>
+// FIXME: I seriously doubt there is any good reason for keeping
+// these types separated from the generic xtype machinery. There
+// is nothing special in them, which would be tightly connected
+// to the table printer. Especially as they are already tested
+// by xtypes-test.c. --mj
+
/** xt_size **/
-static struct unit_definition xtype_units_size[] = {
- [SIZE_UNIT_BYTE] = { "", 1LLU, 1 },
- [SIZE_UNIT_KILOBYTE] = { "KB", 1024LLU, 1 },
- [SIZE_UNIT_MEGABYTE] = { "MB", 1024LLU * 1024LLU, 1 },
- [SIZE_UNIT_GIGABYTE] = { "GB", 1024LLU * 1024LLU * 1024LLU, 1 },
- [SIZE_UNIT_TERABYTE] = { "TB", 1024LLU * 1024LLU * 1024LLU * 1024LLU, 1 },
+static const struct unit_definition xt_size_units[] = {
+ [XT_SIZE_UNIT_BYTE] = { "", 1LLU, 1 },
+ [XT_SIZE_UNIT_KILOBYTE] = { "KB", 1024LLU, 1 },
+ [XT_SIZE_UNIT_MEGABYTE] = { "MB", 1024LLU * 1024LLU, 1 },
+ [XT_SIZE_UNIT_GIGABYTE] = { "GB", 1024LLU * 1024LLU * 1024LLU, 1 },
+ [XT_SIZE_UNIT_TERABYTE] = { "TB", 1024LLU * 1024LLU * 1024LLU * 1024LLU, 1 },
{ 0, 0, 0 }
};
static enum size_units xt_size_auto_units(u64 sz)
{
- if(sz >= xtype_units_size[SIZE_UNIT_TERABYTE].num) {
- return SIZE_UNIT_TERABYTE;
- } else if(sz >= xtype_units_size[SIZE_UNIT_GIGABYTE].num) {
- return SIZE_UNIT_GIGABYTE;
- } else if(sz >= xtype_units_size[SIZE_UNIT_MEGABYTE].num) {
- return SIZE_UNIT_MEGABYTE;
- } else if(sz >= xtype_units_size[SIZE_UNIT_KILOBYTE].num) {
- return SIZE_UNIT_KILOBYTE;
+ if(sz >= xt_size_units[XT_SIZE_UNIT_TERABYTE].num) {
+ return XT_SIZE_UNIT_TERABYTE;
+ } else if(sz >= xt_size_units[XT_SIZE_UNIT_GIGABYTE].num) {
+ return XT_SIZE_UNIT_GIGABYTE;
+ } else if(sz >= xt_size_units[XT_SIZE_UNIT_MEGABYTE].num) {
+ return XT_SIZE_UNIT_MEGABYTE;
+ } else if(sz >= xt_size_units[XT_SIZE_UNIT_KILOBYTE].num) {
+ return XT_SIZE_UNIT_KILOBYTE;
}
- return SIZE_UNIT_BYTE;
+ return XT_SIZE_UNIT_BYTE;
}
static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool)
{
u64 curr_val = *(u64*) src;
-
- if(fmt == XTYPE_FMT_RAW) {
- return mp_printf(pool, "%"PRIu64, curr_val);
- }
-
- uint out_units = SIZE_UNIT_BYTE;
-
- if(fmt == XTYPE_FMT_DEFAULT) {
- curr_val = curr_val;
- out_units = SIZE_UNIT_BYTE;
- } else if(fmt == XTYPE_FMT_PRETTY) {
- // the same as SIZE_UNIT_AUTO
+ uint out_units;
+
+ if(fmt & XT_SIZE_FMT_FIXED_UNIT) {
+ out_units = fmt & ~XT_SIZE_FMT_FIXED_UNIT;
+ } else {
+ switch(fmt) {
+ case XTYPE_FMT_RAW:
+ return mp_printf(pool, "%"PRIu64, curr_val);
+ case XTYPE_FMT_PRETTY:
+ out_units = XT_SIZE_UNIT_AUTO;
+ break;
+ case XTYPE_FMT_DEFAULT:
+ default:
+ out_units = XT_SIZE_UNIT_BYTE;
+ break;
+ }
+ }
+
+ if(out_units == XT_SIZE_UNIT_AUTO) {
out_units = xt_size_auto_units(curr_val);
- curr_val = curr_val / xtype_units_size[out_units].num;
- } else if((fmt & SIZE_UNITS_FIXED) != 0 && (fmt & SIZE_UNIT_AUTO) == SIZE_UNIT_AUTO) {
- // the same as XTYPE_FMT_PRETTY
- out_units = xt_size_auto_units(curr_val);
- curr_val = curr_val / xtype_units_size[out_units].num;
- } else if((fmt & SIZE_UNITS_FIXED) != 0) {
- curr_val = curr_val / xtype_units_size[fmt & ~SIZE_UNITS_FIXED].num;
- out_units = fmt & ~SIZE_UNITS_FIXED;
}
+ ASSERT(out_units < ARRAY_SIZE(xt_size_units));
- return mp_printf(pool, "%"PRIu64"%s", curr_val, xtype_units_size[out_units].unit);
+ curr_val = curr_val / xt_size_units[out_units].num;
+ return mp_printf(pool, "%"PRIu64"%s", curr_val, xt_size_units[out_units].unit);
}
static const char *xt_size_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool)
{
- if(opt_str == NULL) {
- return "NULL is not supported as a column argument.";
- }
-
if(strlen(opt_str) == 0 || strcmp(opt_str, "B") == 0 || strcmp(opt_str, "Bytes") == 0) {
- *dest = SIZE_UNIT_BYTE | SIZE_UNITS_FIXED;
+ *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_BYTE);
return NULL;
}
if(strcmp(opt_str, "auto") == 0) {
- *dest = SIZE_UNIT_AUTO | SIZE_UNITS_FIXED;
+ *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_AUTO);
return NULL;
}
- int unit_idx = xtype_unit_parser(opt_str, xtype_units_size);
+ int unit_idx = xtype_unit_parser(opt_str, xt_size_units);
if(unit_idx == -1) {
return mp_printf(pool, "Unknown option '%s'", opt_str);
}
- *dest = unit_idx | SIZE_UNITS_FIXED;
+ *dest = XT_SIZE_FMT_UNIT(unit_idx);
return NULL;
}
{
errno = 0;
char *units_start = NULL;
+ // FIXME: Use str_to_u64() here to avoid troubles with strtoul()
+ // FIXME: Besides, who promises that u64 fits in unsigned long int?
u64 parsed = strtoul(str, &units_start, 10);
if(str == units_start) {
return mp_printf(pool, "Invalid value of size: '%s'.", str);
return NULL;
}
- int unit_idx = xtype_unit_parser(units_start, xtype_units_size);
+ int unit_idx = xtype_unit_parser(units_start, xt_size_units);
if(unit_idx == -1) {
return mp_printf(pool, "Invalid units: '%s'.", units_start);
}
- *(u64*) dest = parsed * xtype_units_size[unit_idx].num;
+ // FIXME: Detect overflow?
+ *(u64*) dest = parsed * xt_size_units[unit_idx].num;
return NULL;
}
break;
}
- return mp_printf(pool, "%s", formatted_time_buf);
+ return mp_strdup(pool, formatted_time_buf);
}
static const char *xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool)
{
- if(opt_str == NULL) {
- return "NULL is not supported as a column argument.";
- }
-
if(strcasecmp(opt_str, "timestamp") == 0 || strcasecmp(opt_str, "epoch") == 0) {
- *dest = TIMESTAMP_EPOCH;
+ *dest = XT_TIMESTAMP_FMT_EPOCH;
return NULL;
} else if(strcasecmp(opt_str, "datetime") == 0) {
- *dest = TIMESTAMP_DATETIME;
+ *dest = XT_TIMESTAMP_FMT_DATETIME;
return NULL;
}
{
errno = 0;
char *parse_end = NULL;
+ // FIXME: Again, why strtoul()?
u64 parsed = strtoul(str, &parse_end, 10);
if(str == parse_end) {
return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
#define xt_timestamp ucw_xt_timestamp
#endif
+/* Size, possibly with a unit. Internally represented as u64. */
+
+extern const struct xtype xt_size;
+
enum size_units {
- SIZE_UNIT_BYTE,
- SIZE_UNIT_KILOBYTE,
- SIZE_UNIT_MEGABYTE,
- SIZE_UNIT_GIGABYTE,
- SIZE_UNIT_TERABYTE,
- SIZE_UNIT_AUTO
+ XT_SIZE_UNIT_BYTE,
+ XT_SIZE_UNIT_KILOBYTE,
+ XT_SIZE_UNIT_MEGABYTE,
+ XT_SIZE_UNIT_GIGABYTE,
+ XT_SIZE_UNIT_TERABYTE,
+ XT_SIZE_UNIT_AUTO
};
-#define TIMESTAMP_EPOCH XTYPE_FMT_RAW
-#define TIMESTAMP_DATETIME XTYPE_FMT_PRETTY
+#define XT_SIZE_FMT_UNIT(_unit) (_unit | XT_SIZE_FMT_FIXED_UNIT)
+#define XT_SIZE_FMT_FIXED_UNIT XTYPE_FMT_CUSTOM
-#define SIZE_UNITS_FIXED 0x40000000
+#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_size, .set_col_opt = table_set_col_opt }
+#define TBL_COL_SIZE_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_size, .set_col_opt = table_set_col_opt }
+
+TABLE_COL_PROTO(size, u64)
+
+/* Timestamp. Internally represented as time_t. */
+
+#define XT_TIMESTAMP_FMT_EPOCH XTYPE_FMT_RAW
+#define XT_TIMESTAMP_FMT_DATETIME XTYPE_FMT_PRETTY
-extern const struct xtype xt_size;
extern const struct xtype xt_timestamp;
-#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_size, .set_col_opt = table_set_col_opt }
#define TBL_COL_TIMESTAMP(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_timestamp, .set_col_opt = table_set_col_opt }
+#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_timestamp, .set_col_opt = table_set_col_opt }
-#define TBL_COL_SIZE_FMT(_name, _width, _units) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_size, .set_col_opt = table_set_col_opt }
-#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_timestamp, .set_col_opt = table_set_col_opt}
-
-TABLE_COL_PROTO(size, u64)
TABLE_COL_PROTO(timestamp, u64)
#endif