NeoMutt  2024-04-25-34-g585158
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
subset.c
Go to the documentation of this file.
1
38#include "config.h"
39#include <limits.h>
40#include <stdint.h>
41#include <stdio.h>
42#include "mutt/lib.h"
43#include "subset.h"
44#include "set.h"
45
46struct Notify;
47
51static const struct Mapping ConfigEventNames[] = {
52 // clang-format off
53 { "NT_CONFIG_SET", NT_CONFIG_SET },
54 { "NT_CONFIG_RESET", NT_CONFIG_RESET },
55 { "NT_CONFIG_DELETED", NT_CONFIG_DELETED },
56 { NULL, 0 },
57 // clang-format on
58};
59
63int elem_list_sort(const void *a, const void *b, void *sdata)
64{
65 if (!a || !b)
66 return 0;
67
68 const struct HashElem *hea = *(struct HashElem const *const *) a;
69 const struct HashElem *heb = *(struct HashElem const *const *) b;
70
71 return mutt_istr_cmp(hea->key.strkey, heb->key.strkey);
72}
73
79struct HashElem **get_elem_list(struct ConfigSet *cs)
80{
81 if (!cs)
82 return NULL;
83
84 struct HashElem **he_list = mutt_mem_calloc(1024, sizeof(struct HashElem *));
85 size_t index = 0;
86
87 struct HashWalkState walk = { 0 };
88 struct HashElem *he = NULL;
89
90 while ((he = mutt_hash_walk(cs->hash, &walk)))
91 {
92 he_list[index++] = he;
93 if (index == 1022)
94 break; /* LCOV_EXCL_LINE */
95 }
96
97 mutt_qsort_r(he_list, index, sizeof(struct HashElem *), elem_list_sort, NULL);
98
99 return he_list;
100}
101
108void cs_subset_free(struct ConfigSubset **ptr)
109{
110 if (!ptr || !*ptr)
111 return;
112
113 struct ConfigSubset *sub = *ptr;
114
115 struct EventConfig ev_c = { sub, NULL, NULL };
116 mutt_debug(LL_NOTIFY, "NT_CONFIG_DELETED: ALL\n");
118
119 if (sub->cs && sub->name)
120 {
121 char scope[256] = { 0 };
122 snprintf(scope, sizeof(scope), "%s:", sub->name);
123
124 // We don't know if any config items have been set,
125 // so search for anything with a matching scope.
126 struct HashElem **he_list = get_elem_list(sub->cs);
127 for (size_t i = 0; he_list[i]; i++)
128 {
129 const char *item = he_list[i]->key.strkey;
130 if (mutt_str_startswith(item, scope) != 0)
131 {
132 cs_uninherit_variable(sub->cs, item);
133 }
134 }
135 FREE(&he_list);
136 }
137
138 notify_free(&sub->notify);
139 FREE(&sub->name);
140 FREE(ptr);
141}
142
152struct ConfigSubset *cs_subset_new(const char *name, struct ConfigSubset *sub_parent,
153 struct Notify *not_parent)
154{
155 struct ConfigSubset *sub = mutt_mem_calloc(1, sizeof(*sub));
156
157 if (sub_parent)
158 {
159 sub->parent = sub_parent;
160 sub->cs = sub_parent->cs;
161 }
162
163 if (name)
164 {
165 char scope[256] = { 0 };
166
167 if (sub_parent && sub_parent->name)
168 snprintf(scope, sizeof(scope), "%s:%s", sub_parent->name, name);
169 else
170 mutt_str_copy(scope, name, sizeof(scope));
171
172 sub->name = mutt_str_dup(scope);
173 }
174
175 sub->notify = notify_new();
176 notify_set_parent(sub->notify, not_parent);
177
178 return sub;
179}
180
187struct HashElem *cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
188{
189 if (!sub || !name)
190 return NULL;
191
192 char scope[256] = { 0 };
193 if (sub->name)
194 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
195 else
196 mutt_str_copy(scope, name, sizeof(scope));
197
198 return cs_get_elem(sub->cs, scope);
199}
200
208struct HashElem *cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
209{
210 if (!sub)
211 return NULL;
212
213 struct HashElem *he = cs_subset_lookup(sub, name);
214 if (he)
215 return he;
216
217 if (sub->parent)
218 {
219 // Create parent before creating name
220 he = cs_subset_create_inheritance(sub->parent, name);
221 }
222
223 if (!he)
224 return NULL;
225
226 char scope[256] = { 0 };
227 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
228 return cs_inherit_variable(sub->cs, he, scope);
229}
230
238 struct HashElem *he, enum NotifyConfig ev)
239{
240 if (!sub || !he)
241 return;
242
243 struct HashElem *he_base = cs_get_base(he);
244 struct EventConfig ev_c = { sub, he_base->key.strkey, he };
245 mutt_debug(LL_NOTIFY, "%s: %s\n",
247 notify_send(sub->notify, NT_CONFIG, ev, &ev_c);
248}
249
259 struct HashElem *he, struct Buffer *err)
260{
261 if (!sub)
262 return INT_MIN;
263
264 return cs_he_native_get(sub->cs, he, err);
265}
266
276 intptr_t value, struct Buffer *err)
277{
278 if (!sub)
279 return CSR_ERR_CODE;
280
281 int rc = cs_he_native_set(sub->cs, he, value, err);
282
283 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
285
286 return rc;
287}
288
297int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name,
298 intptr_t value, struct Buffer *err)
299{
300 struct HashElem *he = cs_subset_create_inheritance(sub, name);
301
302 return cs_subset_he_native_set(sub, he, value, err);
303}
304
312int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
313{
314 if (!sub)
315 return CSR_ERR_CODE;
316
317 int rc = cs_he_reset(sub->cs, he, err);
318
319 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
321
322 return rc;
323}
324
332int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he,
333 struct Buffer *result)
334{
335 if (!sub)
336 return CSR_ERR_CODE;
337
338 return cs_he_string_get(sub->cs, he, result);
339}
340
348int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name,
349 struct Buffer *result)
350{
351 struct HashElem *he = cs_subset_create_inheritance(sub, name);
352
353 return cs_subset_he_string_get(sub, he, result);
354}
355
364int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he,
365 const char *value, struct Buffer *err)
366{
367 if (!sub)
368 return CSR_ERR_CODE;
369
370 int rc = cs_he_string_set(sub->cs, he, value, err);
371
372 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
374
375 return rc;
376}
377
386int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name,
387 const char *value, struct Buffer *err)
388{
389 struct HashElem *he = cs_subset_create_inheritance(sub, name);
390
391 return cs_subset_he_string_set(sub, he, value, err);
392}
393
402int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he,
403 const char *value, struct Buffer *err)
404{
405 if (!sub)
406 return CSR_ERR_CODE;
407
408 int rc = cs_he_string_plus_equals(sub->cs, he, value, err);
409
410 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
412
413 return rc;
414}
415
425 const char *value, struct Buffer *err)
426{
427 if (!sub)
428 return CSR_ERR_CODE;
429
430 int rc = cs_he_string_minus_equals(sub->cs, he, value, err);
431
432 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
434
435 return rc;
436}
437
445int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
446{
447 if (!sub)
448 return CSR_ERR_CODE;
449
450 const char *name = mutt_str_dup(he->key.strkey);
451 int rc = cs_he_delete(sub->cs, he, err);
452
453 if (CSR_RESULT(rc) == CSR_SUCCESS)
454 {
455 struct EventConfig ev_c = { sub, name, NULL };
456 mutt_debug(LL_NOTIFY, "NT_CONFIG_DELETED: %s\n", name);
458 }
459
460 FREE(&name);
461 return rc;
462}
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:175
int cs_he_string_plus_equals(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: set.c:864
int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:391
int cs_he_delete(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Delete config item from a config set.
Definition: set.c:981
int cs_he_string_set(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:588
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:160
int cs_he_native_set(const struct ConfigSet *cs, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition: set.c:708
intptr_t cs_he_native_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Natively get the value of a HashElem config item.
Definition: set.c:813
struct HashElem * cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *he_parent, const char *name)
Create in inherited config item.
Definition: set.c:347
int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: set.c:663
int cs_he_string_minus_equals(const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: set.c:923
void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
Remove an inherited config item.
Definition: set.c:376
#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_SUCCESS
Action completed successfully.
Definition: set.h:35
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
int elem_list_sort(const void *a, const void *b, void *sdata)
Compare two HashElem pointers to config - Implements sort_t -.
Definition: subset.c:63
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem's in a Hash Table.
Definition: hash.c:489
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:52
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:62
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:95
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:75
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:413
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:231
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:582
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
Parse the 'set' command.
void mutt_qsort_r(void *base, size_t nmemb, size_t size, sort_t compar, void *sdata)
Sort an array, where the comparator has access to opaque data rather than requiring global variables.
Definition: qsort_r.c:67
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
Container for lots of config items.
Definition: set.h:252
struct HashTable * hash
Hash Table: "$name" -> ConfigDef.
Definition: set.h:253
A set of inherited config items.
Definition: subset.h:47
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
const char * name
Scope name of Subset.
Definition: subset.h:48
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
struct ConfigSubset * parent
Parent Subset.
Definition: subset.h:50
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition: subset.h:49
A config-change event.
Definition: subset.h:71
const struct ConfigSubset * sub
Config Subset.
Definition: subset.h:72
const char * name
Name of config item that changed.
Definition: subset.h:73
struct HashElem * he
Config item that changed.
Definition: subset.h:74
The item stored in a Hash Table.
Definition: hash.h:43
union HashKey key
Key representing the data.
Definition: hash.h:45
Cursor to iterate through a Hash Table.
Definition: hash.h:132
Mapping between user-readable string and a constant.
Definition: mapping.h:33
Notification API.
Definition: notify.c:53
int cs_subset_he_string_minus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: subset.c:424
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:332
int cs_subset_he_native_set(const struct ConfigSubset *sub, struct HashElem *he, intptr_t value, struct Buffer *err)
Natively set the value of a HashElem config item.
Definition: subset.c:275
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:297
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
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition: subset.c:445
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:79
int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Reset a config item to its initial value.
Definition: subset.c:312
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:348
int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:364
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:386
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition: subset.c:208
struct ConfigSubset * cs_subset_new(const char *name, struct ConfigSubset *sub_parent, struct Notify *not_parent)
Create a new Config Subset.
Definition: subset.c:152
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition: subset.c:108
static const struct Mapping ConfigEventNames[]
Names for logging.
Definition: subset.c:51
int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: subset.c:402
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:187
void cs_subset_notify_observers(const struct ConfigSubset *sub, struct HashElem *he, enum NotifyConfig ev)
Notify all observers of an event.
Definition: subset.c:237
Subset of Config Items.
NotifyConfig
Config notification types.
Definition: subset.h:61
@ NT_CONFIG_DELETED
Config item has been deleted.
Definition: subset.h:64
@ NT_CONFIG_RESET
Config item has been reset to initial, or parent, value.
Definition: subset.h:63
@ NT_CONFIG_SET
Config item has been set.
Definition: subset.h:62
const char * strkey
String key.
Definition: hash.h:35