]> mj.ucw.cz Git - libucw.git/blob - ucw/xtypes-basic.c
tableprinter: code cleanup, update of formats of double
[libucw.git] / ucw / xtypes-basic.c
1 /*
2  *      UCW Library -- Basic Extended Types
3  *
4  *      (c) 2014 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/mempool.h>
12 #include <ucw/strtonum.h>
13 #include <ucw/xtypes.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <inttypes.h>
17
18 #define XTYPE_NUM_FORMAT(_type, _fmt, _typename) static const char *xt_##_typename##_format(void *src, u32 fmt UNUSED, struct mempool *pool) \
19 {\
20   return mp_printf(pool, _fmt, *(_type *)src);\
21 }
22
23 #define XTYPE_NUM_PARSE(_typename) static const char *xt_##_typename##_parse(const char *str, void *dest, struct mempool *pool UNUSED)\
24 {\
25   return str_to_##_typename(dest, str, NULL, 10 | STN_WHOLE | STN_MINUS | STN_PLUS | STN_HEX | STN_BIN | STN_OCT);\
26 }
27
28 #define XTYPE_NUM_STRUCT(_type, _typename) const struct xtype xt_##_typename = {\
29   .size = sizeof(_type),\
30   .name = #_typename,\
31   .parse = xt_##_typename##_parse,\
32   .format = xt_##_typename##_format,\
33 };
34
35 #define XTYPE_NUM_DEF(_type, _fmt, _typename) XTYPE_NUM_FORMAT(_type, _fmt, _typename) \
36   XTYPE_NUM_PARSE(_typename)\
37   XTYPE_NUM_STRUCT(_type, _typename)
38
39 XTYPE_NUM_DEF(int, "%d", int)
40 XTYPE_NUM_DEF(s64, "%" PRId64, s64)
41 XTYPE_NUM_DEF(intmax_t, "%jd", intmax)
42 XTYPE_NUM_DEF(uint, "%u", uint)
43 XTYPE_NUM_DEF(u64, "%" PRIu64, u64)
44 XTYPE_NUM_DEF(uintmax_t, "%ju", uintmax)
45
46 /* double */
47
48 static const char *xt_double_format(void *src, u32 fmt, struct mempool *pool)
49 {
50   switch(fmt) {
51   case XTYPE_FMT_RAW:
52     return mp_printf(pool, "%.10lf", *(double *)src);
53   case XTYPE_FMT_PRETTY:
54     return mp_printf(pool, "%.2lf", *(double *)src);
55
56   case XTYPE_FMT_DEFAULT:
57   default:
58     return mp_printf(pool, "%.5lf", *(double *)src);
59   }
60 }
61
62 static const char *xt_double_parse(const char *str, void *dest, struct mempool *pool UNUSED)
63 {
64   char *endptr = NULL;
65   size_t sz = strlen(str);
66   errno = 0;
67   double result = strtod(str, &endptr);
68   if(endptr != str + sz) return "Could not parse double.";
69   if(errno == ERANGE) return "Could not parse double: overflow happend during parsing";
70
71   *((double *) dest) = result;
72
73   return NULL;
74 }
75
76 const struct xtype xt_double = {
77   .size = sizeof(double),
78   .name = "double",
79   .parse = xt_double_parse,
80   .format = xt_double_format,
81 };
82
83 /* bool */
84
85 static const char *xt_bool_format(void *src, u32 fmt UNUSED, struct mempool *pool) // (struct table *tbl, int col, enum xtype_fmt fmt, bool val)
86 {
87   switch(fmt) {
88     case XTYPE_FMT_DEFAULT:
89     case XTYPE_FMT_PRETTY:
90       return mp_printf(pool, "%s", *((bool *)src) ? "true" : "false");
91     case XTYPE_FMT_RAW:
92       return mp_printf(pool, "%s", *((bool *)src) ? "1" : "0");
93     default:
94       die("Unsupported output type.");
95   }
96 }
97
98 static const char *xt_bool_parse(const char *str, void *dest, struct mempool *pool UNUSED)
99 {
100   if(str[1] == 0) {
101     if(str[0] == '1') {
102       *((bool *)dest) = false;
103       return NULL;
104     }
105     if(str[0] == '1') {
106       *((bool *)dest) = true;
107       return NULL;
108     }
109   }
110
111   if(strcasecmp(str, "false") == 0) {
112     *((bool *)dest) = false;
113     return NULL;
114   }
115
116   if(strcasecmp(str, "true") == 0) {
117     *((bool *)dest) = true;
118     return NULL;
119   }
120
121   return "Could not parse bool.";
122 }
123
124 const struct xtype xt_bool = {
125   .size = sizeof(bool),
126   .name = "bool",
127   .parse = xt_bool_parse,
128   .format = xt_bool_format,
129 };
130
131 /* str */
132
133 static const char *xt_str_format(void *src, u32 fmt UNUSED, struct mempool *pool)
134 {
135   return mp_printf(pool, "%s", *((char **) src));
136 }
137
138 static const char *xt_str_parse(const char *str, void *dest, struct mempool *pool UNUSED)
139 {
140   *((const char **) dest) = str;
141   return NULL;
142 }
143
144 const struct xtype xt_str = {
145   .size = sizeof(char *),
146   .name = "str",
147   .parse = xt_str_parse,
148   .format = xt_str_format,
149 };