NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
subset.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <limits.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include "mutt/lib.h"
35 #include "subset.h"
36 #include "set.h"
37 
38 struct Notify;
39 
43 static const struct Mapping ConfigEventNames[] = {
44  // clang-format off
45  { "NT_CONFIG_SET", NT_CONFIG_SET },
46  { "NT_CONFIG_RESET", NT_CONFIG_RESET },
47  // clang-format on
48  { NULL, 0 },
49 };
50 
59 int elem_list_sort(const void *a, const void *b)
60 {
61  if (!a || !b)
62  return 0;
63 
64  const struct HashElem *hea = *(struct HashElem const *const *) a;
65  const struct HashElem *heb = *(struct HashElem const *const *) b;
66 
67  return mutt_istr_cmp(hea->key.strkey, heb->key.strkey);
68 }
69 
75 struct HashElem **get_elem_list(struct ConfigSet *cs)
76 {
77  if (!cs)
78  return NULL;
79 
80  struct HashElem **list = mutt_mem_calloc(1024, sizeof(struct HashElem *));
81  size_t index = 0;
82 
83  struct HashWalkState walk = { 0 };
84  struct HashElem *he = NULL;
85 
86  while ((he = mutt_hash_walk(cs->hash, &walk)))
87  {
88  list[index++] = he;
89  if (index == 1022)
90  break; /* LCOV_EXCL_LINE */
91  }
92 
93  qsort(list, index, sizeof(struct HashElem *), elem_list_sort);
94 
95  return list;
96 }
97 
104 void cs_subset_free(struct ConfigSubset **ptr)
105 {
106  if (!ptr || !*ptr)
107  return;
108 
109  struct ConfigSubset *sub = *ptr;
110 
111  if (sub->cs && sub->name)
112  {
113  char scope[256];
114  snprintf(scope, sizeof(scope), "%s:", sub->name);
115 
116  // We don't know if any config items have been set,
117  // so search for anything with a matching scope.
118  struct HashElem **list = get_elem_list(sub->cs);
119  for (size_t i = 0; list[i]; i++)
120  {
121  const char *item = list[i]->key.strkey;
122  if (mutt_str_startswith(item, scope) != 0)
123  {
124  cs_uninherit_variable(sub->cs, item);
125  }
126  }
127  FREE(&list);
128  }
129 
130  notify_free(&sub->notify);
131  FREE(&sub->name);
132  FREE(ptr);
133 }
134 
144 struct ConfigSubset *cs_subset_new(const char *name, struct ConfigSubset *sub_parent,
145  struct Notify *not_parent)
146 {
147  struct ConfigSubset *sub = mutt_mem_calloc(1, sizeof(*sub));
148 
149  if (sub_parent)
150  {
151  sub->parent = sub_parent;
152  sub->cs = sub_parent->cs;
153  }
154 
155  if (name)
156  {
157  char scope[256];
158 
159  if (sub_parent && sub_parent->name)
160  snprintf(scope, sizeof(scope), "%s:%s", sub_parent->name, name);
161  else
162  mutt_str_copy(scope, name, sizeof(scope));
163 
164  sub->name = mutt_str_dup(scope);
165  }
166 
167  sub->notify = notify_new();
168  notify_set_parent(sub->notify, not_parent);
169 
170  return sub;
171 }
172 
179 struct HashElem *cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
180 {
181  if (!sub || !name)
182  return NULL;
183 
184  char scope[256];
185  if (sub->name)
186  snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
187  else
188  mutt_str_copy(scope, name, sizeof(scope));
189 
190  return cs_get_elem(sub->cs, scope);
191 }
192 
200 struct HashElem *cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
201 {
202  if (!sub)
203  return NULL;
204 
205  struct HashElem *he = cs_subset_lookup(sub, name);
206  if (he)
207  return he;
208 
209  if (sub->parent)
210  {
211  // Create parent before creating name
212  he = cs_subset_create_inheritance(sub->parent, name);
213  }
214 
215  if (!he)
216  return NULL;
217 
218  char scope[256];
219  snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
220  return cs_inherit_variable(sub->cs, he, scope);
221 }
222 
230  struct HashElem *he, enum NotifyConfig ev)
231 {
232  if (!sub || !he)
233  return;
234 
235  struct HashElem *he_base = cs_get_base(he);
236  struct EventConfig ev_c = { sub, he_base->key.strkey, he };
237  mutt_debug(LL_NOTIFY, "%s: %s\n",
238  NONULL(mutt_map_get_name(ev, ConfigEventNames)), he_base->key.strkey);
239  notify_send(sub->notify, NT_CONFIG, ev, &ev_c);
240 }
241 
250 intptr_t cs_subset_he_native_get(const struct ConfigSubset *sub,
251  struct HashElem *he, struct Buffer *err)
252 {
253  if (!sub)
254  return INT_MIN;
255 
256  return cs_he_native_get(sub->cs, he, err);
257 }
258 
268  const char *name, struct Buffer *err)
269 {
270  struct HashElem *he = cs_subset_create_inheritance(sub, name);
271 
272  return cs_subset_he_native_get(sub, he, err);
273 }
274 
283 int cs_subset_he_native_set(const struct ConfigSubset *sub, struct HashElem *he,
284  intptr_t value, struct Buffer *err)
285 {
286  if (!sub)
287  return CSR_ERR_CODE;
288 
289  int rc = cs_he_native_set(sub->cs, he, value, err);
290 
291  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
293 
294  return rc;
295 }
296 
305 int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name,
306  intptr_t value, struct Buffer *err)
307 {
308  struct HashElem *he = cs_subset_create_inheritance(sub, name);
309 
310  return cs_subset_he_native_set(sub, he, value, err);
311 }
312 
320 int cs_subset_he_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
321 {
322  if (!sub)
323  return CSR_ERR_CODE;
324 
325  int rc = cs_he_reset(sub->cs, he, err);
326 
327  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
329 
330  return rc;
331 }
332 
340 int cs_subset_str_reset(const struct ConfigSubset *sub, const char *name, struct Buffer *err)
341 {
342  struct HashElem *he = cs_subset_create_inheritance(sub, name);
343 
344  return cs_subset_he_reset(sub, he, err);
345 }
346 
354 int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he,
355  struct Buffer *result)
356 {
357  if (!sub)
358  return CSR_ERR_CODE;
359 
360  return cs_he_string_get(sub->cs, he, result);
361 }
362 
370 int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name,
371  struct Buffer *result)
372 {
373  struct HashElem *he = cs_subset_create_inheritance(sub, name);
374 
375  return cs_subset_he_string_get(sub, he, result);
376 }
377 
386 int cs_subset_he_string_set(const struct ConfigSubset *sub, struct HashElem *he,
387  const char *value, struct Buffer *err)
388 {
389  if (!sub)
390  return CSR_ERR_CODE;
391 
392  int rc = cs_he_string_set(sub->cs, he, value, err);
393 
394  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
396 
397  return rc;
398 }
399 
408 int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name,
409  const char *value, struct Buffer *err)
410 {
411  struct HashElem *he = cs_subset_create_inheritance(sub, name);
412 
413  return cs_subset_he_string_set(sub, he, value, err);
414 }
415 
424 int cs_subset_he_string_plus_equals(const struct ConfigSubset *sub, struct HashElem *he,
425  const char *value, struct Buffer *err)
426 {
427  if (!sub)
428  return CSR_ERR_CODE;
429 
430  int rc = cs_he_string_plus_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 
446 int cs_subset_str_string_plus_equals(const struct ConfigSubset *sub, const char *name,
447  const char *value, struct Buffer *err)
448 {
449  struct HashElem *he = cs_subset_create_inheritance(sub, name);
450 
451  return cs_subset_he_string_plus_equals(sub, he, value, err);
452 }
453 
462 int cs_subset_he_string_minus_equals(const struct ConfigSubset *sub, struct HashElem *he,
463  const char *value, struct Buffer *err)
464 {
465  if (!sub)
466  return CSR_ERR_CODE;
467 
468  int rc = cs_he_string_minus_equals(sub->cs, he, value, err);
469 
470  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
472 
473  return rc;
474 }
475 
484 int cs_subset_str_string_minus_equals(const struct ConfigSubset *sub, const char *name,
485  const char *value, struct Buffer *err)
486 {
487  struct HashElem *he = cs_subset_create_inheritance(sub, name);
488 
489  return cs_subset_he_string_minus_equals(sub, he, value, err);
490 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
union HashKey key
Key representing the data.
Definition: hash.h:46
Container for lots of config items.
Definition: set.h:259
NotifyConfig
Config notification types.
Definition: subset.h:60
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct ConfigSubset * parent
Parent Subset.
Definition: subset.h:50
int cs_subset_str_string_minus_equals(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Remove from a config item by string.
Definition: subset.c:484
Log of notifications.
Definition: logging.h:45
void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
Remove an inherited config item.
Definition: set.c:331
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
A collection of config items.
const char * name
Scope name of Subset.
Definition: subset.h:48
Cursor to iterate through a Hash Table.
Definition: hash.h:122
struct HashElem * cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *parent, const char *name)
Create in inherited config item.
Definition: set.c:306
A config-change event.
Definition: subset.h:69
String manipulation buffer.
Definition: buffer.h:33
void cs_subset_notify_observers(const struct ConfigSubset *sub, struct HashElem *he, enum NotifyConfig ev)
Notify all observers of an event.
Definition: subset.c:229
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
intptr_t cs_subset_str_native_get(const struct ConfigSubset *sub, const char *name, struct Buffer *err)
Natively get the value of a string config item.
Definition: subset.c:267
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition: subset.c:104
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:179
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:462
struct HashElem * cs_subset_create_inheritance(const struct ConfigSubset *sub, const char *name)
Create a Subset config item (inherited)
Definition: subset.c:200
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:75
#define CSR_RESULT(x)
Definition: set.h:52
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:386
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:790
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:346
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:305
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
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:408
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:320
struct HashElem * he
Config item that changed.
Definition: subset.h:73
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:354
#define CSR_SUC_NO_CHANGE
The value hasn&#39;t changed.
Definition: set.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:250
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:941
struct HashTable * hash
HashTable storing the config items.
Definition: set.h:261
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
A set of inherited config items.
Definition: subset.h:46
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
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:858
int cs_subset_str_reset(const struct ConfigSubset *sub, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: subset.c:340
int elem_list_sort(const void *a, const void *b)
Sort two HashElem pointers to config.
Definition: subset.c:59
Notification API.
Definition: notify.c:50
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition: subset.h:49
Subset of Config Items.
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:370
struct HashElem * cs_get_base(struct HashElem *he)
Find the root Config Item.
Definition: set.c:189
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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:543
Config item has been set.
Definition: subset.h:62
struct ConfigSubset * cs_subset_new(const char *name, struct ConfigSubset *sub_parent, struct Notify *not_parent)
Create a new Config Subset.
Definition: subset.c:144
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
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:424
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:749
const char * strkey
String key.
Definition: hash.h:36
int cs_subset_str_string_plus_equals(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Add to a config item by string.
Definition: subset.c:446
#define FREE(x)
Definition: memory.h:40
Mapping between user-readable string and a constant.
Definition: mapping.h:31
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash Table.
Definition: hash.c:481
Config item has been reset to initial, or parent, value.
Definition: subset.h:63
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:618
The item stored in a Hash Table.
Definition: hash.h:43
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:93
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
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:685
Convenience wrapper for the library headers.
struct HashElem * cs_get_elem(const struct ConfigSet *cs, const char *name)
Get the HashElem representing a config item.
Definition: set.c:204
const struct ConfigSubset * sub
Config Subset.
Definition: subset.h:71
const char * name
Name of config item that changed.
Definition: subset.h:72
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:283
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171