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