NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
config_type.c
Go to the documentation of this file.
1
36#include "config.h"
37#include <stddef.h>
38#include <assert.h>
39#include <limits.h>
40#include <stdint.h>
41#include <stdio.h>
42#include "mutt/lib.h"
43#include "config/lib.h"
44#include "expando.h"
45
49static void expando_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
50{
51 struct Expando **a = var;
52 if (!*a)
53 return;
54
55 expando_free(a);
56}
57
61static int expando_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
62 const char *value, struct Buffer *err)
63{
64 /* Store empty string list as NULL */
65 if (value && (value[0] == '\0'))
66 value = NULL;
67
68 if (!value && (cdef->type & D_NOT_EMPTY))
69 {
70 buf_printf(err, _("Option %s may not be empty"), cdef->name);
72 }
73
74 int rc = CSR_SUCCESS;
75
76 if (var)
77 {
78 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
79 cdef->data;
80 struct Expando *exp = expando_parse(value, defs, err);
81 if (!exp && !buf_is_empty(err))
82 {
83 char opt[128] = { 0 };
84 // L10N: e.g. "Option index_format:" plus an error message
85 snprintf(opt, sizeof(opt), _("Option %s: "), cdef->name);
86 buf_insert(err, 0, opt);
87 return CSR_ERR_INVALID;
88 }
89
90 if (expando_equal(exp, *(struct Expando **) var))
91 {
92 expando_free(&exp);
94 }
95
96 if (startup_only(cdef, err))
97 {
98 expando_free(&exp);
100 }
101
102 if (cdef->validator)
103 {
104 rc = cdef->validator(cs, cdef, (intptr_t) exp, err);
105
106 if (CSR_RESULT(rc) != CSR_SUCCESS)
107 {
108 expando_free(&exp);
109 return rc | CSR_INV_VALIDATOR;
110 }
111 }
112
113 expando_destroy(cs, var, cdef);
114
115 *(struct Expando **) var = exp;
116
117 if (!exp)
118 rc |= CSR_SUC_EMPTY;
119 }
120 else
121 {
122 if (cdef->type & D_INTERNAL_INITIAL_SET)
123 FREE(&cdef->initial);
124
126 cdef->initial = (intptr_t) mutt_str_dup(value);
127 }
128
129 return rc;
130}
131
135static int expando_string_get(const struct ConfigSet *cs, void *var,
136 const struct ConfigDef *cdef, struct Buffer *result)
137{
138 const char *str = NULL;
139
140 if (var)
141 {
142 struct Expando *exp = *(struct Expando **) var;
143 if (exp)
144 str = exp->string;
145 }
146 else
147 {
148 str = (char *) cdef->initial;
149 }
150
151 if (!str)
152 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
153
154 buf_addstr(result, str);
155 return CSR_SUCCESS;
156}
157
161static int expando_native_set(const struct ConfigSet *cs, void *var,
162 const struct ConfigDef *cdef, intptr_t value,
163 struct Buffer *err)
164{
165 int rc;
166
167 struct Expando *exp_value = (struct Expando *) value;
168 if (!exp_value && (cdef->type & D_NOT_EMPTY))
169 {
170 buf_printf(err, _("Option %s may not be empty"), cdef->name);
172 }
173
174 struct Expando *exp_old = *(struct Expando **) var;
175 if (expando_equal(exp_value, exp_old))
177
178 if (startup_only(cdef, err))
180
181 if (cdef->validator)
182 {
183 rc = cdef->validator(cs, cdef, value, err);
184
185 if (CSR_RESULT(rc) != CSR_SUCCESS)
186 return rc | CSR_INV_VALIDATOR;
187 }
188
189 expando_free(var);
190
191 struct Expando *exp_copy = NULL;
192
193 if (exp_value)
194 {
195 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
196 cdef->data;
197 exp_copy = expando_parse(exp_value->string, defs, err);
198 }
199
200 rc = CSR_SUCCESS;
201 if (!exp_copy)
202 rc |= CSR_SUC_EMPTY;
203
204 *(struct Expando **) var = exp_copy;
205 return rc;
206}
207
211static intptr_t expando_native_get(const struct ConfigSet *cs, void *var,
212 const struct ConfigDef *cdef, struct Buffer *err)
213{
214 if (!cs || !var || !cdef)
215 return INT_MIN; /* LCOV_EXCL_LINE */
216
217 struct Expando *exp = *(struct Expando **) var;
218
219 return (intptr_t) exp;
220}
221
225static int expando_string_plus_equals(const struct ConfigSet *cs, void *var,
226 const struct ConfigDef *cdef,
227 const char *value, struct Buffer *err)
228{
229 /* Skip if the value is missing or empty string*/
230 if (!value || (value[0] == '\0'))
232
233 if (value && startup_only(cdef, err))
235
236 int rc = CSR_SUCCESS;
237
238 char *str = NULL;
239 struct Expando *exp_old = *(struct Expando **) var;
240
241 if (exp_old && exp_old->string)
242 mutt_str_asprintf(&str, "%s%s", exp_old->string, value);
243 else
244 str = mutt_str_dup(value);
245
246 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *) cdef->data;
247 struct Expando *exp_new = expando_parse(str, defs, err);
248 FREE(&str);
249
250 if (!exp_new && !buf_is_empty(err))
251 {
252 char opt[128] = { 0 };
253 // L10N: e.g. "Option index_format:" plus an error message
254 snprintf(opt, sizeof(opt), _("Option %s: "), cdef->name);
255 buf_insert(err, 0, opt);
256 return CSR_ERR_INVALID;
257 }
258
259 if (expando_equal(exp_new, exp_old))
260 {
261 expando_free(&exp_new); // LCOV_EXCL_LINE
262 return CSR_SUCCESS | CSR_SUC_NO_CHANGE; // LCOV_EXCL_LINE
263 }
264
265 if (cdef->validator)
266 {
267 rc = cdef->validator(cs, cdef, (intptr_t) exp_new, err);
268
269 if (CSR_RESULT(rc) != CSR_SUCCESS)
270 {
271 expando_free(&exp_new);
272 return rc | CSR_INV_VALIDATOR;
273 }
274 }
275
276 expando_destroy(cs, var, cdef);
277 *(struct Expando **) var = exp_new;
278
279 return rc;
280}
281
285static int expando_reset(const struct ConfigSet *cs, void *var,
286 const struct ConfigDef *cdef, struct Buffer *err)
287{
288 if (!cs || !var || !cdef)
289 return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
290
291 struct Expando *exp = NULL;
292 const char *initial = (const char *) cdef->initial;
293
294 if (initial)
295 {
296 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
297 cdef->data;
298 exp = expando_parse(initial, defs, err);
299 }
300
301 if (expando_equal(exp, *(struct Expando **) var))
302 {
303 expando_free(&exp);
305 }
306
307 if (startup_only(cdef, err))
308 {
309 expando_free(&exp);
311 }
312
313 int rc = CSR_SUCCESS;
314
315 if (cdef->validator)
316 {
317 rc = cdef->validator(cs, cdef, (intptr_t) exp, err);
318
319 if (CSR_RESULT(rc) != CSR_SUCCESS)
320 {
321 expando_destroy(cs, &exp, cdef);
322 return rc | CSR_INV_VALIDATOR;
323 }
324 }
325
326 if (!exp)
327 rc |= CSR_SUC_EMPTY;
328
329 expando_destroy(cs, var, cdef);
330
331 *(struct Expando **) var = exp;
332 return rc;
333}
334
338const struct ConfigSetType CstExpando = {
340 "expando",
346 NULL, // string_minus_equals
349};
350
358const struct Expando *cs_subset_expando(const struct ConfigSubset *sub, const char *name)
359{
360 assert(sub && name);
361
362 struct HashElem *he = cs_subset_create_inheritance(sub, name);
363 assert(he);
364
365#ifndef NDEBUG
366 struct HashElem *he_base = cs_get_base(he);
367 assert(DTYPE(he_base->type) == DT_EXPANDO);
368#endif
369
370 intptr_t value = cs_subset_he_native_get(sub, he, NULL);
371 assert(value != INT_MIN);
372
373 return (const struct Expando *) value;
374}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:290
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
size_t buf_insert(struct Buffer *buf, size_t offset, const char *s)
Add a string in the middle of a buffer.
Definition: buffer.c:255
Convenience wrapper for the config headers.
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:160
static bool startup_only(const struct ConfigDef *cdef, struct Buffer *err)
Validator function for D_ON_STARTUP.
Definition: set.h:296
#define CSR_ERR_INVALID
Value hasn't been set.
Definition: set.h:38
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition: set.h:44
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
const struct ConfigSetType CstExpando
Config type representing an Expando.
Definition: config_type.c:338
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:358
struct Expando * expando_parse(const char *str, const struct ExpandoDefinition *defs, struct Buffer *err)
Parse an Expando string.
Definition: expando.c:74
void expando_free(struct Expando **ptr)
Free an Expando object.
Definition: expando.c:54
bool expando_equal(const struct Expando *a, const struct Expando *b)
Compare two expandos.
Definition: expando.c:129
Parsed Expando.
static void expando_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy an Expando object - Implements ConfigSetType::destroy() -.
Definition: config_type.c:49
static int expando_native_set(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set an Expando object from an Expando config item - Implements ConfigSetType::native_get() -.
Definition: config_type.c:161
static intptr_t expando_native_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an Expando object from an Expando config item - Implements ConfigSetType::native_get() -.
Definition: config_type.c:211
static int expando_reset(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset an Expando to its initial value - Implements ConfigSetType::reset() -.
Definition: config_type.c:285
static int expando_string_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get an Expando as a string - Implements ConfigSetType::string_get() -.
Definition: config_type.c:135
static int expando_string_plus_equals(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Add to an Expando by string - Implements ConfigSetType::string_plus_equals() -.
Definition: config_type.c:225
static int expando_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set an Expando by string - Implements ConfigSetType::string_set() -.
Definition: config_type.c:61
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:797
String manipulation buffer.
Definition: buffer.h:36
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition: set.h:82
intptr_t data
Extra variable data.
Definition: set.h:68
intptr_t initial
Initial value.
Definition: set.h:67
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
Container for lots of config items.
Definition: set.h:252
A set of inherited config items.
Definition: subset.h:47
Definition of a format string.
Definition: definition.h:52
Parsed Expando trees.
Definition: expando.h:41
const char * string
Pointer to the parsed string.
Definition: expando.h:42
The item stored in a Hash Table.
Definition: hash.h:43
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:44
intptr_t cs_subset_he_native_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Natively get the value of a HashElem config item.
Definition: subset.c:258
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition: subset.c:208
#define DTYPE(t)
Definition: types.h:50
#define D_INTERNAL_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:90
@ DT_EXPANDO
an expando
Definition: types.h:34
#define D_NOT_EMPTY
Empty strings are not allowed.
Definition: types.h:80