]> mj.ucw.cz Git - libucw.git/blob - ucw/xtypes.h
Tests: xtypes-test sets an explicit timezone
[libucw.git] / ucw / xtypes.h
1 /*
2  *      UCW Library -- Extended Types
3  *
4  *      (c) 2014--2015 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 #ifndef _UCW_XTYPES_H
11 #define _UCW_XTYPES_H
12
13 #ifdef CONFIG_UCW_CLEAN_ABI
14 #define xt_bool ucw_xt_bool
15 #define xt_double ucw_xt_double
16 #define xt_int ucw_xt_int
17 #define xt_intmax ucw_xt_intmax
18 #define xt_s64 ucw_xt_s64
19 #define xt_str ucw_xt_str
20 #define xt_u64 ucw_xt_u64
21 #define xt_uint ucw_xt_uint
22 #define xt_uintmax ucw_xt_uintmax
23 #define xtype_format_fmt ucw_xtype_format_fmt
24 #define xtype_parse_fmt ucw_xtype_parse_fmt
25 #define xtype_unit_parser ucw_xtype_unit_parser
26 #endif
27
28 struct mempool;
29
30 /***
31  * Definitions of types
32  * ~~~~~~~~~~~~~~~~~~~~
33  ***/
34
35 /**
36  * A parsing callback. Takes a string, interprets it as a value of the particular
37  * xtype and stores it where @dest points. Returns NULL on success and an error message
38  * otherwise. It may allocate memory from the @pool and the parsed value can contain
39  * pointers to this memory.
40  **/
41 typedef const char * (*xtype_parser)(const char *str, void *dest, struct mempool *pool);
42
43 /**
44  * A formatting callback. Takes a value of the particular xtype and a formatting
45  * mode @fmt (see below for how the modes work) and returns a string representation
46  * of the value. The string can be allocated from the @pool, but it does not have to.
47  *
48  * When @fmt is set to `XTYPE_FMT_DEFAULT`, the resulting string should be
49  * parseable via the parsing callback and yield a semantically equivalent value.
50  **/
51 typedef const char * (*xtype_formatter)(void *src, u32 fmt, struct mempool *pool);
52
53 /**
54  * Formatting of values is controlled by a mode parameter, which is generally
55  * a 32-bit integer. If the most significant bit is clear, it is one of generic
56  * well-known modes (`XTYPE_FMT_`'something'), which can be passed to all formatters
57  * and if it is not understood, it acts like `XTYPE_FMT_DEFAULT`. When the most
58  * significant bit is set, the meaning of the mode is specific to the particular
59  * xtype.
60  **/
61 enum xtype_fmt {
62   XTYPE_FMT_DEFAULT = 0,        // Default format: readable, but not hostile to machine parsing
63   XTYPE_FMT_RAW = 1,            // Raw data with no frills
64   XTYPE_FMT_PRETTY = 2,         // Try to please humans (e.g., like "ls -h")
65   XTYPE_FMT_CUSTOM = 0x80000000,
66 };
67
68 /**
69  * A callback for parsing non-generic formatting modes. See `xtype_parser` for more
70  * details. It is usually called via `xtype_parse_fmt`, which handles the generic modes.
71  **/
72 typedef const char * (*xtype_fmt_parser)(const char *str, u32 *dest, struct mempool *pool);
73
74 /**
75  * A callback for constructing a string representation of non-generic formatting modes,
76  * analogous to `xtype_formatter`. It is usually called via `xtype_format_fmt`,
77  * which handles the generic modes. Returns an empty string for unknown modes.
78  **/
79 typedef const char * (*xtype_fmt_formatter)(u32 fmt, struct mempool *pool);
80
81 /**
82  * This structure describes an xtype. Among other things, it points to callback
83  * functions handling this xtype.
84  **/
85 struct xtype {
86   size_t size;                          // How many bytes does a single value occupy
87   const char *name;                     // Name used in debug messages
88   xtype_parser parse;                   // Parsing callback
89   xtype_formatter format;               // Formatting callback
90   xtype_fmt_parser parse_fmt;           // Format mode parsing callback (optional)
91   xtype_fmt_formatter format_fmt;       // Format mode formatting callback (optional)
92 };
93
94 /**
95  * Construct a formatting mode from its string representation. It is a wrapper
96  * around the `xtype_fmt_parser` hook, which handles generic modes first.
97  *
98  * The generic modes are called `default`, `raw`, and `pretty`.
99  **/
100 const char *xtype_parse_fmt(const struct xtype *xt, const char *str, u32 *dest, struct mempool *pool);
101
102 /**
103  * Construct a string representation of a formatting mode. It is a wrapper
104  * around the `xtype_fmt_formatter` hook, which handles generic modes first.
105  * Returns an empty string for unknown modes.
106  **/
107 const char *xtype_format_fmt(struct xtype *xt, u32 fmt, struct mempool *pool);
108
109 /***
110  * Basic pre-defined types
111  * ~~~~~~~~~~~~~~~~~~~~~~~
112  *
113  * We provide xtypes for many basic data types:
114  *
115  * * `xt_bool`
116  * * `xt_double` -- in addition to the generic formatting modes, you can use
117  *   `XT_DOUBLE_FMT_PREC(`'n'`)` to generate a mode for fixed formatting with
118  *   'n' decimal places.
119  * * `xt_int`
120  * * `xt_intmax`
121  * * `xt_s64`
122  * * `xt_str` -- string, represented by a `const char *`
123  * * `xt_u64`
124  * * `xt_uint`
125  * * `xt_uintmax`
126  ***/
127
128 extern const struct xtype xt_bool;
129 extern const struct xtype xt_double;
130 extern const struct xtype xt_int;
131 extern const struct xtype xt_intmax;
132 extern const struct xtype xt_s64;
133 extern const struct xtype xt_str;
134 extern const struct xtype xt_u64;
135 extern const struct xtype xt_uint;
136 extern const struct xtype xt_uintmax;
137
138 // Fixed-precision formats for xt_double
139 #define XT_DOUBLE_FMT_PREC(_prec) (_prec | XT_DOUBLE_FMT_PREC_FLAG)
140 #define XT_DOUBLE_FMT_PREC_FLAG XTYPE_FMT_CUSTOM
141
142 /***
143  * Tables of units
144  * ~~~~~~~~~~~~~~~
145  *
146  * Various xtypes accept values accompanied by a unit of measure.
147  * Units by handled by the xtypes themselves, but we provide a couple
148  * of generic functions for their convenience.
149  ***/
150
151 /**
152  * Each unit is defined by a conversion ratio, which is a fraction with 64-bit numerator
153  * and denominator. Therefore, a value of 'x' units is interpreted as 'x' * 'num' / 'denom'.
154  **/
155 struct unit_definition {
156   const char *unit;             // Symbol (name of the unit, as appended to values)
157   u64 num;                      // Numerator
158   u64 denom;                    // Denominator
159 };
160
161 /**
162  * Given an array @units of unit definitions (terminated by an all-zero entry),
163  * parse a name of a unit and return its index in the array, or -1 if it is not found.
164  **/
165 int xtype_unit_parser(const char *str, const struct unit_definition *units);
166
167 #endif