NeoMutt  2025-01-09-117-gace867
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
80struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
81{
82 struct HashElemArray hea = ARRAY_HEAD_INITIALIZER;
83
84 if (!cs)
85 return hea;
86
87 struct HashWalkState walk = { 0 };
88 struct HashElem *he = NULL;
89 while ((he = mutt_hash_walk(cs->hash, &walk)))
90 {
91 if ((flags == GEL_CHANGED_CONFIG) && !cs_he_has_been_set(cs, he))
92 continue;
93
94 ARRAY_ADD(&hea, he);
95 }
96
97 ARRAY_SORT(&hea, elem_list_sort, NULL);
98
99 return hea;
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 HashElemArray hea = get_elem_list(sub->cs, GEL_ALL_CONFIG);
127 struct HashElem **hep = NULL;
128 ARRAY_FOREACH(hep, &hea)
129 {
130 struct HashElem *he = *hep;
131 const char *item = he->key.strkey;
132 if (mutt_str_startswith(item, scope) != 0)
133 {
134 cs_uninherit_variable(sub->cs, item);
135 }
136 }
137 ARRAY_FREE(&hea);
138 }
139
140 notify_free(&sub->notify);
141 FREE(&sub->name);
142 FREE(ptr);
143}
144
154struct ConfigSubset *cs_subset_new(const char *name, struct ConfigSubset *sub_parent,
155 struct Notify *not_parent)
156{
157 struct ConfigSubset *sub = MUTT_MEM_CALLOC(1, struct ConfigSubset);
158
159 if (sub_parent)
160 {
161 sub->parent = sub_parent;
162 sub->cs = sub_parent->cs;
163 }
164
165 if (name)
166 {
167 char scope[256] = { 0 };
168
169 if (sub_parent && sub_parent->name)
170 snprintf(scope, sizeof(scope), "%s:%s", sub_parent->name, name);
171 else
172 mutt_str_copy(scope, name, sizeof(scope));
173
174 sub->name = mutt_str_dup(scope);
175 }
176
177 sub->notify = notify_new();
178 notify_set_parent(sub->notify, not_parent);
179
180 return sub;
181}
182
189struct HashElem *cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
190{
191 if (!sub || !name)
192 return NULL;
193
194 char scope[256] = { 0 };
195 if (sub->name)
196 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
197 else
198 mutt_str_copy(scope, name, sizeof(scope));
199
200 return cs_get_elem(sub->cs, scope);
201}
202
210struct HashElem *cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
211{
212 if (!sub)
213 return NULL;
214
215 struct HashElem *he = cs_subset_lookup(sub, name);
216 if (he)
217 return he;
218
219 if (sub->parent)
220 {
221 // Create parent before creating name
222 he = cs_subset_create_inheritance(sub->parent, name);
223 }
224
225 if (!he)
226 return NULL;
227
228 char scope[256] = { 0 };
229 snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
230 return cs_inherit_variable(sub->cs, he, scope);
231}
232
240 struct HashElem *he, enum NotifyConfig ev)
241{
242 if (!sub || !he)
243 return;
244
245 struct HashElem *he_base = cs_get_base(he);
246 struct EventConfig ev_c = { sub, he_base->key.strkey, he };
247 mutt_debug(LL_NOTIFY, "%s: %s\n",
249 notify_send(sub->notify, NT_CONFIG, ev, &ev_c);
250}
251
261 struct HashElem *he, struct Buffer *err)
262{
263 if (!sub)
264 return INT_MIN;
265
266 return cs_he_native_get(sub->cs, he, err);
267}
268
278 intptr_t value, struct Buffer *err)
279{
280 if (!sub)
281 return CSR_ERR_CODE;
282
283 int rc = cs_he_native_set(sub->cs, he, value, err);
284
285 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
287
288 return rc;
289}
290
299int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name,
300 intptr_t value, struct Buffer *err)
301{
302 struct HashElem *he = cs_subset_create_inheritance(sub, name);
303
304 return cs_subset_he_native_set(sub, he, value, err);
305}
306
314int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
315{
316 if (!sub)
317 return CSR_ERR_CODE;
318
319 int rc = cs_he_reset(sub->cs, he, err);
320
321 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
323
324 return rc;
325}
326
334int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he,
335 struct Buffer *result)
336{
337 if (!sub)
338 return CSR_ERR_CODE;
339
340 return cs_he_string_get(sub->cs, he, result);
341}
342
350int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name,
351 struct Buffer *result)
352{
353 struct HashElem *he = cs_subset_create_inheritance(sub, name);
354
355 return cs_subset_he_string_get(sub, he, result);
356}
357
366int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he,
367 const char *value, struct Buffer *err)
368{
369 if (!sub)
370 return CSR_ERR_CODE;
371
372 int rc = cs_he_string_set(sub->cs, he, value, err);
373
374 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
376
377 return rc;
378}
379
388int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name,
389 const char *value, struct Buffer *err)
390{
391 struct HashElem *he = cs_subset_create_inheritance(sub, name);
392
393 return cs_subset_he_string_set(sub, he, value, err);
394}
395
404int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he,
405 const char *value, struct Buffer *err)
406{
407 if (!sub)
408 return CSR_ERR_CODE;
409
410 int rc = cs_he_string_plus_equals(sub->cs, he, value, err);
411
412 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
414
415 return rc;
416}
417
427 const char *value, struct Buffer *err)
428{
429 if (!sub)
430 return CSR_ERR_CODE;
431
432 int rc = cs_he_string_minus_equals(sub->cs, he, value, err);
433
434 if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
436
437 return rc;
438}
439
447int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
448{
449 if (!sub)
450 return CSR_ERR_CODE;
451
452 const char *name = mutt_str_dup(he->key.strkey);
453 int rc = cs_he_delete(sub->cs, he, err);
454
455 if (CSR_RESULT(rc) == CSR_SUCCESS)
456 {
457 struct EventConfig ev_c = { sub, name, NULL };
458 mutt_debug(LL_NOTIFY, "NT_CONFIG_DELETED: %s\n", name);
460 }
461
462 FREE(&name);
463 return rc;
464}
#define ARRAY_SORT(head, fn, sdata)
Sort an array.
Definition: array.h:335
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:156
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:214
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
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:892
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:399
int cs_he_delete(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
Delete config item from a config set.
Definition: set.c:1009
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:616
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:160
bool cs_he_has_been_set(const struct ConfigSet *cs, struct HashElem *he)
Is the config value different to its initial value?
Definition: set.c:468
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:736
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:841
struct HashElem * cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *he_parent, const char *name)
Create in inherited config item.
Definition: set.c:355
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:691
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:951
void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
Remove an inherited config item.
Definition: set.c:384
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition: set.h:42
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:34
#define CSR_RESULT(x)
Definition: set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:33
#define mutt_debug(LEVEL,...)
Definition: logging2.h:90
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:49
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
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.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
Container for lots of config items.
Definition: set.h:248
A set of inherited config items.
Definition: subset.h:46
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:51
const char * name
Scope name of Subset.
Definition: subset.h:47
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:50
struct ConfigSubset * parent
Parent Subset.
Definition: subset.h:49
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition: subset.h:48
A config-change event.
Definition: subset.h:70
const struct ConfigSubset * sub
Config Subset.
Definition: subset.h:71
const char * name
Name of config item that changed.
Definition: subset.h:72
struct HashElem * he
Config item that changed.
Definition: subset.h:73
The item stored in a Hash Table.
Definition: hash.h:44
union HashKey key
Key representing the data.
Definition: hash.h:46
Cursor to iterate through a Hash Table.
Definition: hash.h:134
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:426
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:334
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:277
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:299
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
int cs_subset_he_delete(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
Delete config item from a config.
Definition: subset.c:447
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:314
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:350
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:366
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:388
struct HashElemArray get_elem_list(struct ConfigSet *cs, enum GetElemListFlags flags)
Create a sorted list of all config items.
Definition: subset.c:80
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition: subset.c:210
struct ConfigSubset * cs_subset_new(const char *name, struct ConfigSubset *sub_parent, struct Notify *not_parent)
Create a new Config Subset.
Definition: subset.c:154
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:404
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:189
void cs_subset_notify_observers(const struct ConfigSubset *sub, struct HashElem *he, enum NotifyConfig ev)
Notify all observers of an event.
Definition: subset.c:239
Subset of Config Items.
NotifyConfig
Config notification types.
Definition: subset.h:60
@ NT_CONFIG_DELETED
Config item has been deleted.
Definition: subset.h:63
@ NT_CONFIG_RESET
Config item has been reset to initial, or parent, value.
Definition: subset.h:62
@ NT_CONFIG_SET
Config item has been set.
Definition: subset.h:61
GetElemListFlags
Flags for get_elem_list()
Definition: subset.h:80
@ GEL_CHANGED_CONFIG
Only config that has been changed.
Definition: subset.h:82
@ GEL_ALL_CONFIG
All the normal config (no synonyms or deprecated)
Definition: subset.h:81
const char * strkey
String key.
Definition: hash.h:36