From: Robert Kessl Date: Tue, 29 Jul 2014 08:45:56 +0000 (+0200) Subject: tableprinter&xtypes: table-types.[ch] moved to xtypes-extra.[ch] X-Git-Tag: v6.1~3^2~28 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=0acb58f9ea7ba6e4c623b4917d0fd3401b37a7f6;p=libucw.git tableprinter&xtypes: table-types.[ch] moved to xtypes-extra.[ch] --- diff --git a/ucw/Makefile b/ucw/Makefile index 5b62dba0..c886cb69 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -38,7 +38,7 @@ LIBUCW_MODS= \ daemon daemon-ctrl \ signames \ opt opt-help opt-conf \ - table table-types xtypes xtypes-basic + table xtypes xtypes-basic xtypes-extra LIBUCW_MAIN_INCLUDES= \ lib.h log.h tbf.h threads.h time.h \ @@ -69,7 +69,7 @@ LIBUCW_MAIN_INCLUDES= \ signames.h \ sighandler.h \ opt.h \ - table.h table-types.h \ + table.h xtypes-extra.h \ xtypes.h ifdef CONFIG_UCW_THREADS diff --git a/ucw/table-test-2.c b/ucw/table-test-2.c index 2625d219..78df449b 100644 --- a/ucw/table-test-2.c +++ b/ucw/table-test-2.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/ucw/table-test.c b/ucw/table-test.c index 64acedb8..06bf7057 100644 --- a/ucw/table-test.c +++ b/ucw/table-test.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/ucw/table-types.c b/ucw/table-types.c deleted file mode 100644 index 4da3ccc8..00000000 --- a/ucw/table-types.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * UCW Library -- Table printer types - * - * (c) 2014 Robert Kessl - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// 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 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 >= 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 XT_SIZE_UNIT_BYTE; -} - -static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool) -{ - u64 curr_val = *(u64*) src; - 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); - } - ASSERT(out_units < ARRAY_SIZE(xt_size_units)); - - 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(strlen(opt_str) == 0 || strcmp(opt_str, "B") == 0 || strcmp(opt_str, "Bytes") == 0) { - *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_BYTE); - return NULL; - } - - if(strcmp(opt_str, "auto") == 0) { - *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_AUTO); - return NULL; - } - - 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 = XT_SIZE_FMT_UNIT(unit_idx); - return NULL; -} - -static const char *xt_size_parse(const char *str, void *dest, struct mempool *pool) -{ - errno = 0; - const char *units_start = NULL; - u64 parsed; - const char *err = str_to_u64(&parsed, str, &units_start, 10 | STN_FLAGS); - if(err != NULL) { - return mp_printf(pool, "Invalid value of size: '%s'; number parser error: %s.", str, err); - } - - if(*units_start == 0) { - *(u64*) dest = (u64) parsed; - return NULL; - } - - int unit_idx = xtype_unit_parser(units_start, xt_size_units); - if(unit_idx == -1) { - return mp_printf(pool, "Invalid units: '%s'.", str); - } - - // Overflow detection - u64 num = xt_size_units[unit_idx].num; - if(parsed && UINT64_MAX / parsed < num) { - return mp_printf(pool, "Size too large: '%s'.", str); - } - - *(u64*) dest = parsed * xt_size_units[unit_idx].num; - return NULL; -} - -TABLE_COL_BODY(size, u64) - -const struct xtype xt_size = { - .size = sizeof(u64), - .name = "size", - .parse = xt_size_parse, - .format = xt_size_format, - .parse_fmt = xt_size_fmt_parse -}; - -/** xt_timestamp **/ - -#define FORMAT_TIME_SIZE 20 // Minimum buffer size - -static const char *xt_timestamp_format(void *src, u32 fmt, struct mempool *pool) -{ - char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 }; - - u64 tmp_time_u64 = *(u64*)src; - time_t tmp_time = (time_t) tmp_time_u64; - struct tm t = *gmtime(&tmp_time); - switch (fmt) { - case XTYPE_FMT_DEFAULT: - case XTYPE_FMT_RAW: - sprintf(formatted_time_buf, "%"PRIu64, tmp_time_u64); - break; - case XTYPE_FMT_PRETTY: - strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t); - break; - default: - ASSERT(0); - break; - } - - return mp_strdup(pool, formatted_time_buf); -} - -static const char *xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool) -{ - if(strcasecmp(opt_str, "timestamp") == 0 || strcasecmp(opt_str, "epoch") == 0) { - *dest = XT_TIMESTAMP_FMT_EPOCH; - return NULL; - } else if(strcasecmp(opt_str, "datetime") == 0) { - *dest = XT_TIMESTAMP_FMT_DATETIME; - return NULL; - } - - return mp_printf(pool, "Invalid column format option: '%s'.", opt_str); -} - -static const char *xt_timestamp_parse(const char *str, void *dest, struct mempool *pool) -{ - errno = 0; - const char *parse_end = NULL; - u64 parsed; - const char *err = str_to_u64(&parsed, str, &parse_end, 10 | STN_FLAGS); - if(str == parse_end) { - return mp_printf(pool, "Invalid value of timestamp: '%s'; number parser error: %s.", str, err); - } - - if(*parse_end == 0) { - *(u64*) dest = (u64) parsed; - return NULL; - } - - struct tm parsed_time; - parse_end = strptime(str, "%F %T", &parsed_time); - if(parse_end == NULL) { - return mp_printf(pool, "Invalid value of timestamp: '%s'.", str); - } - if(*parse_end != 0) { - return mp_printf(pool, "Invalid value of timestamp: '%s'.", str); - } - - time_t tmp_time = mktime(&parsed_time); - *(u64*)dest = (u64) tmp_time; - - return NULL; -} - -TABLE_COL_BODY(timestamp, u64) - -const struct xtype xt_timestamp = { - .size = sizeof(u64), - .name = "timestamp", - .parse = xt_timestamp_parse, - .format = xt_timestamp_format, - .parse_fmt = xt_timestamp_fmt_parse -}; diff --git a/ucw/table-types.h b/ucw/table-types.h deleted file mode 100644 index 0220288d..00000000 --- a/ucw/table-types.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * UCW Library -- Table printer - * - * (c) 2014 Robert Kessl - */ - -#ifndef _UCW_TABLE_TYPES_H -#define _UCW_TABLE_TYPES_H - -#include - -#ifdef CONFIG_UCW_CLEAN_ABI -#define table_col_size ucw_table_col_size -#define table_col_timestamp ucw_table_col_timestamp -#define xt_size ucw_xt_size -#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 { - 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 XT_SIZE_FMT_UNIT(_unit) (_unit | XT_SIZE_FMT_FIXED_UNIT) -#define XT_SIZE_FMT_FIXED_UNIT XTYPE_FMT_CUSTOM - -#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_size } -#define TBL_COL_SIZE_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_size } - -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_timestamp; - -#define TBL_COL_TIMESTAMP(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_timestamp } -#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_timestamp } - -TABLE_COL_PROTO(timestamp, u64) - -#endif diff --git a/ucw/xtypes-extra.c b/ucw/xtypes-extra.c new file mode 100644 index 00000000..589ac2cb --- /dev/null +++ b/ucw/xtypes-extra.c @@ -0,0 +1,219 @@ +/* + * UCW Library -- Table printer types + * + * (c) 2014 Robert Kessl + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// 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 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 >= 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 XT_SIZE_UNIT_BYTE; +} + +static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool) +{ + u64 curr_val = *(u64*) src; + 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); + } + ASSERT(out_units < ARRAY_SIZE(xt_size_units)); + + 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(strlen(opt_str) == 0 || strcmp(opt_str, "B") == 0 || strcmp(opt_str, "Bytes") == 0) { + *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_BYTE); + return NULL; + } + + if(strcmp(opt_str, "auto") == 0) { + *dest = XT_SIZE_FMT_UNIT(XT_SIZE_UNIT_AUTO); + return NULL; + } + + 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 = XT_SIZE_FMT_UNIT(unit_idx); + return NULL; +} + +static const char *xt_size_parse(const char *str, void *dest, struct mempool *pool) +{ + errno = 0; + const char *units_start = NULL; + u64 parsed; + const char *err = str_to_u64(&parsed, str, &units_start, 10 | STN_FLAGS); + if(err != NULL) { + return mp_printf(pool, "Invalid value of size: '%s'; number parser error: %s.", str, err); + } + + if(*units_start == 0) { + *(u64*) dest = (u64) parsed; + return NULL; + } + + int unit_idx = xtype_unit_parser(units_start, xt_size_units); + if(unit_idx == -1) { + return mp_printf(pool, "Invalid units: '%s'.", str); + } + + // Overflow detection + u64 num = xt_size_units[unit_idx].num; + if(parsed && UINT64_MAX / parsed < num) { + return mp_printf(pool, "Size too large: '%s'.", str); + } + + *(u64*) dest = parsed * xt_size_units[unit_idx].num; + return NULL; +} + +TABLE_COL_BODY(size, u64) + +const struct xtype xt_size = { + .size = sizeof(u64), + .name = "size", + .parse = xt_size_parse, + .format = xt_size_format, + .parse_fmt = xt_size_fmt_parse +}; + +/** xt_timestamp **/ + +#define FORMAT_TIME_SIZE 20 // Minimum buffer size + +static const char *xt_timestamp_format(void *src, u32 fmt, struct mempool *pool) +{ + char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 }; + + u64 tmp_time_u64 = *(u64*)src; + time_t tmp_time = (time_t) tmp_time_u64; + struct tm t = *gmtime(&tmp_time); + switch (fmt) { + case XTYPE_FMT_DEFAULT: + case XTYPE_FMT_RAW: + sprintf(formatted_time_buf, "%"PRIu64, tmp_time_u64); + break; + case XTYPE_FMT_PRETTY: + strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t); + break; + default: + ASSERT(0); + break; + } + + return mp_strdup(pool, formatted_time_buf); +} + +static const char *xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool) +{ + if(strcasecmp(opt_str, "timestamp") == 0 || strcasecmp(opt_str, "epoch") == 0) { + *dest = XT_TIMESTAMP_FMT_EPOCH; + return NULL; + } else if(strcasecmp(opt_str, "datetime") == 0) { + *dest = XT_TIMESTAMP_FMT_DATETIME; + return NULL; + } + + return mp_printf(pool, "Invalid column format option: '%s'.", opt_str); +} + +static const char *xt_timestamp_parse(const char *str, void *dest, struct mempool *pool) +{ + errno = 0; + const char *parse_end = NULL; + u64 parsed; + const char *err = str_to_u64(&parsed, str, &parse_end, 10 | STN_FLAGS); + if(str == parse_end) { + return mp_printf(pool, "Invalid value of timestamp: '%s'; number parser error: %s.", str, err); + } + + if(*parse_end == 0) { + *(u64*) dest = (u64) parsed; + return NULL; + } + + struct tm parsed_time; + parse_end = strptime(str, "%F %T", &parsed_time); + if(parse_end == NULL) { + return mp_printf(pool, "Invalid value of timestamp: '%s'.", str); + } + if(*parse_end != 0) { + return mp_printf(pool, "Invalid value of timestamp: '%s'.", str); + } + + time_t tmp_time = mktime(&parsed_time); + *(u64*)dest = (u64) tmp_time; + + return NULL; +} + +TABLE_COL_BODY(timestamp, u64) + +const struct xtype xt_timestamp = { + .size = sizeof(u64), + .name = "timestamp", + .parse = xt_timestamp_parse, + .format = xt_timestamp_format, + .parse_fmt = xt_timestamp_fmt_parse +}; diff --git a/ucw/xtypes-extra.h b/ucw/xtypes-extra.h new file mode 100644 index 00000000..4e76b8dd --- /dev/null +++ b/ucw/xtypes-extra.h @@ -0,0 +1,53 @@ +/* + * UCW Library -- Extended types - extra types + * + * (c) 2014 Robert Kessl + */ + +#ifndef _UCW_XTYPES_EXTRA_H +#define _UCW_XTYPES_EXTRA_H + +#include +#include + +#ifdef CONFIG_UCW_CLEAN_ABI +#define table_col_size ucw_table_col_size +#define table_col_timestamp ucw_table_col_timestamp +#define xt_size ucw_xt_size +#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 { + 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 XT_SIZE_FMT_UNIT(_unit) (_unit | XT_SIZE_FMT_FIXED_UNIT) +#define XT_SIZE_FMT_FIXED_UNIT XTYPE_FMT_CUSTOM + +#define TBL_COL_SIZE(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_size } +#define TBL_COL_SIZE_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_size } + +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_timestamp; + +#define TBL_COL_TIMESTAMP(_name, _width) { .name = _name, .width = _width, .fmt = XTYPE_FMT_DEFAULT, .type_def = &xt_timestamp } +#define TBL_COL_TIMESTAMP_FMT(_name, _width, _fmt) { .name = _name, .width = _width, .fmt = _fmt, .type_def = &xt_timestamp } + +TABLE_COL_PROTO(timestamp, u64) + +#endif diff --git a/ucw/xtypes-test.c b/ucw/xtypes-test.c index 95302036..517e7f2c 100644 --- a/ucw/xtypes-test.c +++ b/ucw/xtypes-test.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include