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 struct unit_definition xtype_units_size[] = {
20 [SIZE_UNIT_BYTE] = { "", 1LLU, 1 },
21 [SIZE_UNIT_KILOBYTE] = { "KB", 1024LLU, 1 },
22 [SIZE_UNIT_MEGABYTE] = { "MB", 1024LLU * 1024LLU, 1 },
23 [SIZE_UNIT_GIGABYTE] = { "GB", 1024LLU * 1024LLU * 1024LLU, 1 },
24 [SIZE_UNIT_TERABYTE] = { "TB", 1024LLU * 1024LLU * 1024LLU * 1024LLU, 1 },
28 static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool)
30 u64 curr_val = *(u64*) src;
32 if(fmt == XTYPE_FMT_RAW) {
33 return mp_printf(pool, "%"PRIu64, curr_val);
36 uint out_units = SIZE_UNIT_BYTE;
38 if(fmt == XTYPE_FMT_DEFAULT) {
40 out_units = SIZE_UNIT_BYTE;
41 } else if(fmt == XTYPE_FMT_PRETTY) {
43 out_units = SIZE_UNIT_BYTE;
44 } else if((fmt & SIZE_UNITS_FIXED) != 0) {
45 curr_val = curr_val / xtype_units_size[fmt & ~SIZE_UNITS_FIXED].num;
46 out_units = fmt & ~SIZE_UNITS_FIXED;
49 return mp_printf(pool, "%"PRIu64"%s", curr_val, xtype_units_size[out_units].unit);
52 static const char *xt_size_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool)
55 return "NULL is not supported as a column argument.";
58 if(strlen(opt_str) == 0 || strcmp(opt_str, "B") == 0 || strcmp(opt_str, "Bytes") == 0) {
59 *dest = SIZE_UNIT_BYTE | SIZE_UNITS_FIXED;
63 int unit_idx = xtype_unit_parser(opt_str, xtype_units_size);
65 return mp_printf(pool, "Unknown option '%s'", opt_str);
68 *dest = unit_idx | SIZE_UNITS_FIXED;
72 static const char *xt_size_parse(const char *str, void *dest, struct mempool *pool)
75 char *units_start = NULL;
76 u64 parsed = strtoul(str, &units_start, 10);
77 if(str == units_start) {
78 return mp_printf(pool, "Invalid value of size: '%s'.", str);
82 return "Error occured during parsing of size.";
85 return "Error: size value either too large or too small.";
88 if(*units_start == 0) {
89 *(u64*) dest = (u64) parsed;
93 int unit_idx = xtype_unit_parser(units_start, xtype_units_size);
95 return mp_printf(pool, "Invalid units: '%s'.", units_start);
98 *(u64*) dest = parsed * xtype_units_size[unit_idx].num;
102 TABLE_COL_BODY(size, u64)
104 const struct xtype xt_size = {
107 .parse = xt_size_parse,
108 .format = xt_size_format,
109 .parse_fmt = xt_size_fmt_parse
114 #define FORMAT_TIME_SIZE 20 // Minimum buffer size
116 static const char *xt_timestamp_format(void *src, u32 fmt, struct mempool *pool)
118 char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 };
120 u64 tmp_time_u64 = *(u64*)src;
121 time_t tmp_time = (time_t) tmp_time_u64;
122 struct tm t = *gmtime(&tmp_time);
124 case XTYPE_FMT_DEFAULT:
126 sprintf(formatted_time_buf, "%"PRIu64, tmp_time_u64);
128 case XTYPE_FMT_PRETTY:
129 strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t);
136 return mp_printf(pool, "%s", formatted_time_buf);
139 static const char *xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool)
141 if(opt_str == NULL) {
142 return "NULL is not supported as a column argument.";
145 if(strcasecmp(opt_str, "timestamp") == 0 || strcasecmp(opt_str, "epoch") == 0) {
146 *dest = TIMESTAMP_EPOCH;
148 } else if(strcasecmp(opt_str, "datetime") == 0) {
149 *dest = TIMESTAMP_DATETIME;
153 return mp_printf(pool, "Invalid column format option: '%s'.", opt_str);
156 static const char *xt_timestamp_parse(const char *str, void *dest, struct mempool *pool)
159 char *parse_end = NULL;
160 u64 parsed = strtoul(str, &parse_end, 10);
161 if(str == parse_end) {
162 return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
164 if(errno == EINVAL) {
165 return "Error occured during parsing of size.";
168 if(errno == ERANGE) {
169 return "Error: size value either too large or too small.";
172 if(*parse_end == 0) {
173 *(u64*) dest = (u64) parsed;
177 struct tm parsed_time;
178 parse_end = strptime(str, "%F %T", &parsed_time);
179 if(parse_end == NULL) {
180 return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
182 if(*parse_end != 0) {
183 return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
186 time_t tmp_time = mktime(&parsed_time);
187 *(u64*)dest = (u64) tmp_time;
192 TABLE_COL_BODY(timestamp, u64)
194 const struct xtype xt_timestamp = {
197 .parse = xt_timestamp_parse,
198 .format = xt_timestamp_format,
199 .parse_fmt = xt_timestamp_fmt_parse