]> mj.ucw.cz Git - libucw.git/blob - ucw/table-types.c
tableprinter: update of iterator macro; bugfix in table_set_col_opt_size
[libucw.git] / ucw / table-types.c
1 #include <ucw/lib.h>
2 #include <ucw/config.h>
3 #include <ucw/table-types.h>
4 #include <ucw/fastbuf.h>
5 #include <ucw/config.h>
6 #include <ucw/table.h>
7 #include <time.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 static const char *unit_suffix[] = {
12   [UNIT_BYTE] = "",
13   [UNIT_KILOBYTE] = "KB",
14   [UNIT_MEGABYTE] = "MB",
15   [UNIT_GIGABYTE] = "GB",
16   [UNIT_TERABYTE] = "TB"
17 };
18
19 static bool table_set_col_opt_size(struct table *tbl, uint col_copy_idx, const char *col_arg, char **err)
20 {
21   int col_type_idx = tbl->column_order[col_copy_idx].idx;
22   if(tbl->columns[col_type_idx].type != COL_TYPE_SIZE) {
23     *err = NULL;
24     return false;
25   }
26
27   if(col_arg == NULL) {
28     *err = NULL;
29     return true;
30   }
31
32   if(strcasecmp(col_arg, "b") == 0 || strcasecmp(col_arg, "bytes") == 0) {
33     tbl->column_order[col_copy_idx].output_type = UNIT_BYTE;
34   }
35
36   tbl->column_order[col_copy_idx].output_type = CELL_OUT_UNINITIALIZED;
37   for(uint i = 0; i < ARRAY_SIZE(unit_suffix); i++) {
38     if(strcasecmp(col_arg, unit_suffix[i]) == 0) {
39       tbl->column_order[col_copy_idx].output_type = i;
40     }
41   }
42
43   if(tbl->column_order[col_copy_idx].output_type == CELL_OUT_UNINITIALIZED) {
44     *err = mp_printf(tbl->pool, "Tableprinter: invalid column format option: '%s' for column %d (counted from 0)", col_arg, col_copy_idx);
45     return true;
46   }
47
48   *err = NULL;
49   return true;
50 }
51
52 struct table_user_type table_type_size = {
53   .set_col_instance_option = table_set_col_opt_size,
54   .type = COL_TYPE_SIZE,
55 };
56
57 static bool table_set_col_opt_timestamp(struct table *tbl, uint col_copy_idx, const char *col_arg, char **err)
58 {
59   int col_type_idx = tbl->column_order[col_copy_idx].idx;
60   if(tbl->columns[col_type_idx].type != COL_TYPE_TIMESTAMP) {
61     *err = NULL;
62     return false;
63   }
64
65   if(col_arg == NULL) {
66     *err = NULL;
67     return true;
68   }
69
70   if(strcasecmp(col_arg, "timestamp") == 0 || strcasecmp(col_arg, "epoch") == 0) {
71     tbl->column_order[col_copy_idx].output_type = TIMESTAMP_EPOCH;
72   } else if(strcasecmp(col_arg, "datetime") == 0) {
73     tbl->column_order[col_copy_idx].output_type = TIMESTAMP_DATETIME;
74   } else {
75     *err = mp_printf(tbl->pool, "Tableprinter: invalid column format option: '%s' for column %d.", col_arg, col_copy_idx);
76     return true;
77   }
78
79   *err = NULL;
80   return true;
81 }
82
83 struct table_user_type table_type_timestamp = {
84   .set_col_instance_option = table_set_col_opt_timestamp,
85   .type = COL_TYPE_TIMESTAMP,
86 };
87
88 void table_col_size_name(struct table *tbl, const char *col_name, u64 val)
89 {
90   int col = table_get_col_idx(tbl, col_name);
91   table_col_size(tbl, col, val);
92 }
93
94 void table_col_size(struct table *tbl, int col, u64 val)
95 {
96   ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
97   ASSERT(tbl->columns[col].type == COL_TYPE_ANY || COL_TYPE_SIZE == tbl->columns[col].type);
98
99   tbl->last_printed_col = col;
100   tbl->row_printing_started = 1;
101
102   static u64 unit_div[] = {
103     [UNIT_BYTE] = (u64) 1,
104     [UNIT_KILOBYTE] = (u64) 1024LLU,
105     [UNIT_MEGABYTE] = (u64) (1024LLU * 1024LLU),
106     [UNIT_GIGABYTE] = (u64) (1024LLU * 1024LLU * 1024LLU),
107     [UNIT_TERABYTE] = (u64) (1024LLU * 1024LLU * 1024LLU * 1024LLU)
108   };
109
110   TBL_COL_ITER(tbl, col, curr_col, curr_col_idx) {
111     // FIXME: do some rounding?
112     uint out_type = 0;
113     if(curr_col->output_type == CELL_OUT_UNINITIALIZED) {
114       val = val / unit_div[UNIT_BYTE];
115       out_type = 0;
116     } else {
117       val = val / unit_div[curr_col->output_type];
118       out_type = curr_col->output_type;
119     }
120
121     curr_col->cell_content = mp_printf(tbl->pool, "%lu%s", val, unit_suffix[out_type]);
122   }
123 }
124
125 #define FORMAT_TIME_SIZE 20     // Minimum buffer size
126
127 void table_col_timestamp_name(struct table *tbl, const char * col_name, u64 val)
128 {
129   int col = table_get_col_idx(tbl, col_name);
130   table_col_size(tbl, col, val);
131 }
132
133 void table_col_timestamp(struct table *tbl, int col, u64 val)
134 {
135   ASSERT_MSG(col < tbl->column_count && col >= 0, "Table column %d does not exist.", col);
136   ASSERT(tbl->columns[col].type == COL_TYPE_ANY || COL_TYPE_TIMESTAMP == tbl->columns[col].type);
137
138   char formatted_time_buf[FORMAT_TIME_SIZE] = { 0 };
139
140   time_t tmp_time = (time_t)val;
141   struct tm t = *gmtime(&tmp_time);
142   TBL_COL_ITER(tbl, col, curr_col, curr_col_idx) {
143     switch (curr_col->output_type) {
144     case TIMESTAMP_EPOCH:
145     case CELL_OUT_UNINITIALIZED:
146       sprintf(formatted_time_buf, "%lu", val);
147       break;
148     case TIMESTAMP_DATETIME:
149       strftime(formatted_time_buf, FORMAT_TIME_SIZE, "%F %T", &t);
150     break;
151     default:
152       abort();
153       break;
154     }
155
156     curr_col->cell_content = mp_printf(tbl->pool, "%s", formatted_time_buf);
157   }
158 }