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