NeoMutt  2025-01-09-81-g753ae0
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 <limits.h>
38#include <stdbool.h>
39#include <stddef.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(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(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(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(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(void *var, const struct ConfigDef *cdef, struct Buffer *result)
136{
137 const char *str = NULL;
138
139 if (var)
140 {
141 struct Expando *exp = *(struct Expando **) var;
142 if (exp)
143 str = exp->string;
144 }
145 else
146 {
147 str = (char *) cdef->initial;
148 }
149
150 if (!str)
151 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
152
153 buf_addstr(result, str);
154 return CSR_SUCCESS;
155}
156
160static int expando_native_set(void *var, const struct ConfigDef *cdef,
161 intptr_t value, struct Buffer *err)
162{
163 int rc;
164
165 struct Expando *exp_value = (struct Expando *) value;
166 if (!exp_value && (cdef->type & D_NOT_EMPTY))
167 {
168 buf_printf(err, _("Option %s may not be empty"), cdef->name);
170 }
171
172 struct Expando *exp_old = *(struct Expando **) var;
173 if (expando_equal(exp_value, exp_old))
175
176 if (startup_only(cdef, err))
178
179 if (cdef->validator)
180 {
181 rc = cdef->validator(cdef, value, err);
182
183 if (CSR_RESULT(rc) != CSR_SUCCESS)
184 return rc | CSR_INV_VALIDATOR;
185 }
186
187 expando_free(var);
188
189 struct Expando *exp_copy = NULL;
190
191 if (exp_value)
192 {
193 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
194 cdef->data;
195 exp_copy = expando_parse(exp_value->string, defs, err);
196 }
197
198 rc = CSR_SUCCESS;
199 if (!exp_copy)
200 rc |= CSR_SUC_EMPTY;
201
202 *(struct Expando **) var = exp_copy;
203 return rc;
204}
205
209static intptr_t expando_native_get(void *var, const struct ConfigDef *cdef, struct Buffer *err)
210{
211 struct Expando *exp = *(struct Expando **) var;
212
213 return (intptr_t) exp;
214}
215
219static int expando_string_plus_equals(void *var, const struct ConfigDef *cdef,
220 const char *value, struct Buffer *err)
221{
222 /* Skip if the value is missing or empty string*/
223 if (!value || (value[0] == '\0'))
225
226 if (value && startup_only(cdef, err))
228
229 int rc = CSR_SUCCESS;
230
231 char *str = NULL;
232 struct Expando *exp_old = *(struct Expando **) var;
233
234 if (exp_old && exp_old->string)
235 mutt_str_asprintf(&str, "%s%s", exp_old->string, value);
236 else
237 str = mutt_str_dup(value);
238
239 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *) cdef->data;
240 struct Expando *exp_new = expando_parse(str, defs, err);
241 FREE(&str);
242
243 if (!exp_new && !buf_is_empty(err))
244 {
245 char opt[128] = { 0 };
246 // L10N: e.g. "Option index_format:" plus an error message
247 snprintf(opt, sizeof(opt), _("Option %s: "), cdef->name);
248 buf_insert(err, 0, opt);
249 return CSR_ERR_INVALID;
250 }
251
252 if (expando_equal(exp_new, exp_old))
253 {
254 expando_free(&exp_new); // LCOV_EXCL_LINE
255 return CSR_SUCCESS | CSR_SUC_NO_CHANGE; // LCOV_EXCL_LINE
256 }
257
258 if (cdef->validator)
259 {
260 rc = cdef->validator(cdef, (intptr_t) exp_new, err);
261
262 if (CSR_RESULT(rc) != CSR_SUCCESS)
263 {
264 expando_free(&exp_new);
265 return rc | CSR_INV_VALIDATOR;
266 }
267 }
268
269 expando_destroy(var, cdef);
270 *(struct Expando **) var = exp_new;
271
272 return rc;
273}
274
278static bool expando_has_been_set(void *var, const struct ConfigDef *cdef)
279{
280 const char *initial = (const char *) cdef->initial;
281
282 struct Expando *exp = *(struct Expando **) var;
283 const char *exp_str = exp ? exp->string : NULL;
284
285 return !mutt_str_equal(initial, exp_str);
286}
287
291static int expando_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
292{
293 struct Expando *exp = NULL;
294 const char *initial = (const char *) cdef->initial;
295
296 if (initial)
297 {
298 const struct ExpandoDefinition *defs = (const struct ExpandoDefinition *)
299 cdef->data;
300 exp = expando_parse(initial, defs, err);
301 }
302
303 if (expando_equal(exp, *(struct Expando **) var))
304 {
305 expando_free(&exp);
307 }
308
309 if (startup_only(cdef, err))
310 {
311 expando_free(&exp);
313 }
314
315 int rc = CSR_SUCCESS;
316
317 if (cdef->validator)
318 {
319 rc = cdef->validator(cdef, (intptr_t) exp, err);
320
321 if (CSR_RESULT(rc) != CSR_SUCCESS)
322 {
323 expando_destroy(&exp, cdef);
324 return rc | CSR_INV_VALIDATOR;
325 }
326 }
327
328 if (!exp)
329 rc |= CSR_SUC_EMPTY;
330
331 expando_destroy(var, cdef);
332
333 *(struct Expando **) var = exp;
334 return rc;
335}
336
340const struct ConfigSetType CstExpando = {
342 "expando",
348 NULL, // string_minus_equals
352};
353
361const struct Expando *cs_subset_expando(const struct ConfigSubset *sub, const char *name)
362{
363 ASSERT(sub && name);
364
365 struct HashElem *he = cs_subset_create_inheritance(sub, name);
366 ASSERT(he);
367
368#ifndef NDEBUG
369 struct HashElem *he_base = cs_get_base(he);
370 ASSERT(CONFIG_TYPE(he_base->type) == DT_EXPANDO);
371#endif
372
373 intptr_t value = cs_subset_he_native_get(sub, he, NULL);
374 ASSERT(value != INT_MIN);
375
376 return (const struct Expando *) value;
377}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
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:256
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_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:340
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:361
struct Expando * expando_parse(const char *str, const struct ExpandoDefinition *defs, struct Buffer *err)
Parse an Expando string.
Definition: expando.c:81
void expando_free(struct Expando **ptr)
Free an Expando object.
Definition: expando.c:61
bool expando_equal(const struct Expando *a, const struct Expando *b)
Compare two expandos.
Definition: expando.c:137
static void expando_destroy(void *var, const struct ConfigDef *cdef)
Destroy an Expando object - Implements ConfigSetType::destroy() -.
Definition: config_type.c:49
static bool expando_has_been_set(void *var, const struct ConfigDef *cdef)
Is the config value different to its initial value? - Implements ConfigSetType::has_been_set() -.
Definition: config_type.c:278
static int expando_native_set(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:160
static intptr_t expando_native_get(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:209
static int expando_reset(void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset an Expando to its initial value - Implements ConfigSetType::reset() -.
Definition: config_type.c:291
static int expando_string_get(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(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:219
static int expando_string_set(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:55
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:254
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:804
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
Sidebar Expando definitions.
#define ASSERT(COND)
Definition: signal2.h:60
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 ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition: set.h:81
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
A set of inherited config items.
Definition: subset.h:46
Definition of a format string.
Definition: definition.h:44
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:44
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
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:260
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition: subset.c:210
#define CONFIG_TYPE(t)
Definition: types.h:49
#define D_INTERNAL_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:89
@ DT_EXPANDO
an expando
Definition: types.h:34
#define D_NOT_EMPTY
Empty strings are not allowed.
Definition: types.h:79