1 /* 2 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** @file 18 * Config file parser. 19 */ 20 #ifndef _USUAL_CFPARSER_H_ 21 #define _USUAL_CFPARSER_H_ 22 23 #include <usual/base.h> 24 25 /** 26 * @name Simple line-by-line parser 27 * @{ 28 */ 29 30 /** Callback signarure for @ref parse_ini_file() */ 31 typedef bool (*cf_handler_f)(void *arg, bool is_sect, const char *key, const char *val); 32 33 /** 34 * Simple parser, launches callback for each line 35 */ 36 bool parse_ini_file(const char *fn, cf_handler_f user_handler, void *arg) _MUSTCHECK; 37 38 /* @} */ 39 40 /** 41 * @name Complex parser with variable setting. 42 * @{ 43 */ 44 45 /** @name Per-key flags 46 * @{ 47 */ 48 49 /** The pointer is absolute */ 50 #define CF_VAL_ABS 0 51 52 /** The pointer is relative to base */ 53 #define CF_VAL_REL (1<<1) 54 55 /** Value must not be changed on reload */ 56 #define CF_NO_RELOAD (1<<2) 57 58 /** Value can only be read */ 59 #define CF_READONLY (1<<3) 60 61 /** @} */ 62 63 /** 64 * Helper structure for passing key info to CfOps 65 */ 66 struct CfValue { 67 void *value_p; 68 const void *extra; 69 const char *key_name; 70 char *buf; 71 int buflen; 72 }; 73 74 /** 75 * Callbacks for setting and getting a variable value. 76 * 77 * Getter requires temp buf, returns string pointer, which 78 * may or may not point to temp buf. Getter is optional. 79 */ 80 struct CfOps { 81 bool (*setter)(struct CfValue *cv, const char *value); 82 const char *(*getter)(struct CfValue *cv); 83 const void *op_extra; 84 }; 85 86 /** 87 * Parameter description 88 */ 89 struct CfKey { 90 /** Parameter name */ 91 const char *key_name; 92 /** Type-specific functions, called with absolute pointer */ 93 struct CfOps op; 94 /** Flags: CF_VAL_ABS, CF_VAL_REL */ 95 int flags; 96 /** Absolute or relative offset */ 97 uintptr_t key_ofs; 98 /** Default value as string */ 99 const char *def_value; 100 }; 101 102 /** 103 * Section description 104 */ 105 struct CfSect { 106 /** Section name */ 107 const char *sect_name; 108 109 /** Key list */ 110 const struct CfKey *key_list; 111 112 /** Get base pointer to dynamic sections (optional) */ 113 void *(*base_lookup)(void *top_base, const char *sect_name); 114 115 /** Set dynamic keys (optional) */ 116 bool (*set_key)(void *base, const char *key, const char *val); 117 118 /** Get dynamic keys (optional) */ 119 const char *(*get_key)(void *base, const char *key, char *buf, int buflen); 120 121 /** New section callback (optional) */ 122 bool (*section_start)(void *top_base, const char *sect_name); 123 }; 124 125 /** 126 * Top-level config information 127 */ 128 struct CfContext { 129 /** Section list */ 130 const struct CfSect *sect_list; 131 /** Top-level base pointer, needed for relative addressing */ 132 void *base; 133 /** If set, then CF_NO_RELOAD keys cannot be changed anymore */ 134 bool loaded; 135 }; 136 137 /** 138 * @name Type-specific helpers 139 * @{ 140 */ 141 142 /** Setter for string */ 143 bool cf_set_str(struct CfValue *cv, const char *value); 144 /** Setter for filename */ 145 bool cf_set_filename(struct CfValue *cv, const char *value); 146 /** Setter for int */ 147 bool cf_set_int(struct CfValue *cv, const char *value); 148 /** Setter for unsigned int */ 149 bool cf_set_uint(struct CfValue *cv, const char *value); 150 /** Setter for time-usec */ 151 bool cf_set_time_usec(struct CfValue *cv, const char *value); 152 /** Setter for time-double */ 153 bool cf_set_time_double(struct CfValue *cv, const char *value); 154 /** Setter for lookup */ 155 bool cf_set_lookup(struct CfValue *cv, const char *value); 156 157 /** Getter for string */ 158 const char *cf_get_str(struct CfValue *cv); 159 /** Getter for int */ 160 const char *cf_get_int(struct CfValue *cv); 161 /** Getter for unsigned int */ 162 const char *cf_get_uint(struct CfValue *cv); 163 /** Getter for time-usec */ 164 const char *cf_get_time_usec(struct CfValue *cv); 165 /** Getter for time-double */ 166 const char *cf_get_time_double(struct CfValue *cv); 167 /** Getter for int lookup */ 168 const char *cf_get_lookup(struct CfValue *cv); 169 170 /** @} */ 171 172 /** 173 * @name Shortcut CfOps for well-known types 174 * @{ 175 */ 176 177 /** Ops for string */ 178 #define CF_STR { cf_set_str, cf_get_str } 179 /** Ops for filename */ 180 #define CF_FILE { cf_set_filename, cf_get_str } 181 /** Ops for integer */ 182 #define CF_INT { cf_set_int, cf_get_int } 183 /** Ops for unsigned integer */ 184 #define CF_UINT { cf_set_uint, cf_get_uint } 185 /** Ops for boolean */ 186 #define CF_BOOL { cf_set_int, cf_get_int } 187 /** Ops for time as usec */ 188 #define CF_TIME_USEC { cf_set_time_usec, cf_get_time_usec } 189 /** Ops for time as double */ 190 #define CF_TIME_DOUBLE { cf_set_time_double, cf_get_time_double } 191 /** Ops for lookup, takes table as argument */ 192 #define CF_LOOKUP(t) { cf_set_lookup, cf_get_lookup, t } 193 194 /** @} */ 195 196 /** 197 * Lookup entry for CF_LOOKUP table. 198 */ 199 struct CfLookup { 200 const char *name; 201 int value; 202 }; 203 204 /** 205 * Helper to describe CfKey with absolute addressing 206 */ 207 #define CF_ABS(name, ops, var, flags, def) \ 208 { name, ops, flags | CF_VAL_ABS, (uintptr_t)&(var), def } 209 210 /** 211 * Helper to describe CfKey with relative addressing. 212 * 213 * Before using it defined CF_REL_BASE to base struct. 214 * 215 * The var should be field in that struct. 216 * 217 * @code 218 * struct Foo { 219 * char *foo_name; 220 * }; 221 * #define CF_REL_BASE struct Foo 222 * ... 223 * CF_REL("name", CF_STR, foo_name, 0, NULL) 224 * ... 225 * #undef CF_REL_BASE 226 * @endcode 227 */ 228 #define CF_REL(name, ops, var, flags, def) \ 229 { name, ops, flags | CF_VAL_REL, offsetof(CF_REL_BASE, var), def } 230 231 /** 232 * Load config from file. 233 */ 234 bool cf_load_file(const struct CfContext *cf, const char *fn) _MUSTCHECK; 235 236 /** 237 * Get single value. 238 */ 239 const char *cf_get(const struct CfContext *cf, const char *sect, const char *var, char *buf, int buflen); 240 241 /** 242 * Set single value. 243 */ 244 bool cf_set(const struct CfContext *cf, const char *sect, const char *var, const char *val); 245 246 /* @} */ 247 248 #endif 249