2 * UCW Library -- Table printer types
4 * (c) 2014 Robert Kessl <robert.kessl@economia.cz>
8 #include <ucw/table-types.h>
9 #include <ucw/fastbuf.h>
10 #include <ucw/table.h>
19 static const char *unit_suffix[] = {
20 [SIZE_UNIT_BYTE] = "",
21 [SIZE_UNIT_KILOBYTE] = "KB",
22 [SIZE_UNIT_MEGABYTE] = "MB",
23 [SIZE_UNIT_GIGABYTE] = "GB",
24 [SIZE_UNIT_TERABYTE] = "TB"
27 static u64 unit_div[] = {
28 [SIZE_UNIT_BYTE] = 1LLU,
29 [SIZE_UNIT_KILOBYTE] = 1024LLU,
30 [SIZE_UNIT_MEGABYTE] = 1024LLU * 1024LLU,
31 [SIZE_UNIT_GIGABYTE] = 1024LLU * 1024LLU * 1024LLU,
32 [SIZE_UNIT_TERABYTE] = 1024LLU * 1024LLU * 1024LLU * 1024LLU
35 static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool)
37 u64 curr_val = *(u64*) src;
39 if(fmt == XTYPE_FMT_RAW) {
40 return mp_printf(pool, "%"PRIu64, curr_val);
43 uint out_type = SIZE_UNIT_BYTE;
45 if(fmt == XTYPE_FMT_DEFAULT) {
46 curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
47 out_type = SIZE_UNIT_BYTE;
48 } else if(fmt == XTYPE_FMT_PRETTY) {
49 curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
50 out_type = SIZE_UNIT_BYTE;
51 } else if((fmt & SIZE_UNITS_FIXED) != 0) {
52 curr_val = curr_val / unit_div[fmt & ~SIZE_UNITS_FIXED];
53 out_type = fmt & ~SIZE_UNITS_FIXED;
56 return mp_printf(pool, "%"PRIu64"%s", curr_val, unit_suffix[out_type]);
59 static const char * xt_size_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool UNUSED)
62 return "NULL is not supported as a column argument.";
65 if(strlen(opt_str) == 0 || strcasecmp(opt_str, "b") == 0 || strcasecmp(opt_str, "bytes") == 0) {
66 *dest = SIZE_UNIT_BYTE | SIZE_UNITS_FIXED;
70 for(uint i = SIZE_UNIT_BYTE; i <= SIZE_UNIT_TERABYTE; i++) {
71 if(strcasecmp(opt_str, unit_suffix[i]) == 0) {
72 *dest = i | SIZE_UNITS_FIXED;
77 return "Unknown option.";
80 static const char *xt_size_parse(const char *str, void *dest, struct mempool *pool UNUSED)
83 char *units_start = NULL;
84 u64 parsed = strtol(str, &units_start, 10);
85 if(str == units_start) {
86 return mp_printf(pool, "Invalid value of size: '%s'.", str);
88 if(*units_start == 0) {
89 *(u64*) dest = (u64) parsed;
93 if(errno == EINVAL || errno == ERANGE) {
94 return mp_printf(pool, "Invalid value of size: '%s'.", str);
97 for(uint i = 0; i < ARRAY_SIZE(unit_suffix); i++) {
98 if(strcmp(unit_suffix[i], units_start) == 0) {
99 *(u64*) dest = parsed * unit_div[i];
104 return mp_printf(pool, "Invalid format of size: '%s'.", str);
107 TABLE_COL_BODY(size, u64)
109 const struct xtype xt_size = {
112 .parse = xt_size_parse,
113 .format = xt_size_format,
114 .parse_fmt = xt_size_fmt_parse
119 #define FORMAT_TIME_SIZE 20 // Minimum buffer size
121 static const char *xt_timestamp_format(void *src, u32 fmt, struct mempool *pool)
123 char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 };
125 u64 tmp_time_u64 = *(u64*)src;
126 time_t tmp_time = (time_t) tmp_time_u64;
127 struct tm t = *gmtime(&tmp_time);
129 case XTYPE_FMT_DEFAULT:
131 sprintf(formatted_time_buf, "%"PRIu64, tmp_time_u64);
133 case XTYPE_FMT_PRETTY:
134 strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t);
141 return mp_printf(pool, "%s", formatted_time_buf);
144 static const char * xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool)
146 if(opt_str == NULL) {
147 return "NULL is not supported as a column argument.";
150 if(strcasecmp(opt_str, "timestamp") == 0 || strcasecmp(opt_str, "epoch") == 0) {
151 *dest = TIMESTAMP_EPOCH;
153 } else if(strcasecmp(opt_str, "datetime") == 0) {
154 *dest = TIMESTAMP_DATETIME;
158 return mp_printf(pool, "Invalid column format option: '%s'.", opt_str);
161 TABLE_COL_BODY(timestamp, u64)
163 const struct xtype xt_timestamp = {
166 //.parse = xt_timestamp_parse,
167 .format = xt_timestamp_format,
168 .parse_fmt = xt_timestamp_fmt_parse