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