]> granicus.if.org Git - neomutt/commitdiff
config: add config subsets
authorRichard Russon <rich@flatcap.org>
Wed, 10 Jul 2019 16:37:29 +0000 (17:37 +0100)
committerRichard Russon <rich@flatcap.org>
Sat, 13 Jul 2019 23:25:45 +0000 (00:25 +0100)
Makefile.autosetup
config/lib.h
config/set.c
config/set.h
config/subset.c [new file with mode: 0644]
config/subset.h [new file with mode: 0644]
config/types.h

index 5173c8ceec49b8f65aa15c873b47080a7b93eb15..1b05f382ca68efd14eab9b95c3df0f847f9a03e3 100644 (file)
@@ -230,7 +230,7 @@ LIBCONFIG=  libconfig.a
 LIBCONFIGOBJS= config/address.o config/bool.o config/dump.o config/enum.o \
                config/long.o config/mbtable.o config/number.o \
                config/quad.o config/regex.o config/set.o \
-               config/slist.o config/sort.o config/string.o
+               config/slist.o config/sort.o config/string.o config/subset.o
 
 CLEANFILES+=   $(LIBCONFIG) $(LIBCONFIGOBJS)
 MUTTLIBS+=     $(LIBCONFIG)
index dba8ed7cef5d13e15bab14dda3e97707089bfe42..ba289680ddfb651c6848337ee9d4829f65eac813 100644 (file)
@@ -40,6 +40,7 @@
  * | config/slist.c      | @subpage config_slist      |
  * | config/sort.c       | @subpage config_sort       |
  * | config/string.c     | @subpage config_string     |
+ * | config/subset.c     | @subpage config_subset     |
  */
 
 #ifndef MUTT_CONFIG_LIB_H
@@ -59,6 +60,7 @@
 #include "slist.h"
 #include "sort.h"
 #include "string3.h"
+#include "subset.h"
 #include "types.h"
 
 #endif /* MUTT_CONFIG_LIB_H */
index 0db5755caffa1129708a6f99473e0edd45898b47..24d236cce3c2277b585e0f73ef7b34a720b68d49 100644 (file)
@@ -334,6 +334,19 @@ struct HashElem *cs_inherit_variable(const struct ConfigSet *cs,
   return he;
 }
 
+/**
+ * cs_uninherit_variable - Remove an inherited config item
+ * @param cs   Config items
+ * @param name Name of config item to remove
+ */
+void cs_uninherit_variable(const struct ConfigSet *cs, const char *name)
+{
+  if (!cs || !name)
+    return;
+
+  mutt_hash_delete(cs->hash, name, NULL);
+}
+
 /**
  * cs_notify_observers - Notify all observers of an event
  * @param cs   Config items
@@ -574,14 +587,14 @@ int cs_he_string_set(const struct ConfigSet *cs, struct HashElem *he,
     struct Inheritance *i = he->data;
     struct HashElem *he_base = get_base(he);
     cdef = he_base->data;
-    var = &i->var;
     cst = cs_get_type_def(cs, he_base->type);
+    var = &i->var;
   }
   else
   {
     cdef = he->data;
-    var = cdef->var;
     cst = cs_get_type_def(cs, he->type);
+    var = cdef->var;
   }
 
   if (!cst)
@@ -651,8 +664,9 @@ int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buf
       return cs_he_string_get(cs, i->parent, result);
 
     // inherited, value set
-    cdef = i->parent->data;
-    cst = cs_get_type_def(cs, i->parent->type);
+    struct HashElem *he_base = get_base(he);
+    cdef = he_base->data;
+    cst = cs_get_type_def(cs, he_base->type);
     var = &i->var;
   }
   else
@@ -718,14 +732,14 @@ int cs_he_native_set(const struct ConfigSet *cs, struct HashElem *he,
     struct Inheritance *i = he->data;
     struct HashElem *he_base = get_base(he);
     cdef = he_base->data;
-    var = &i->var;
     cst = cs_get_type_def(cs, he_base->type);
+    var = &i->var;
   }
   else
   {
     cdef = he->data;
-    var = cdef->var;
     cst = cs_get_type_def(cs, he->type);
+    var = cdef->var;
   }
 
   if (!cst)
@@ -776,14 +790,14 @@ int cs_str_native_set(const struct ConfigSet *cs, const char *name,
     struct Inheritance *i = he->data;
     struct HashElem *he_base = get_base(he);
     cdef = he_base->data;
-    var = &i->var;
     cst = cs_get_type_def(cs, he_base->type);
+    var = &i->var;
   }
   else
   {
     cdef = he->data;
-    var = cdef->var;
     cst = cs_get_type_def(cs, he->type);
+    var = cdef->var;
   }
 
   if (!cst)
index 12b4b3e3e097cfece81e1138955afcde4047e46f..f0d375e2c4cf1ffa0b5a797d443abf13d424e311 100644 (file)
@@ -213,6 +213,7 @@ const struct ConfigSetType *cs_get_type_def(const struct ConfigSet *cs, unsigned
 bool             cs_register_type(struct ConfigSet *cs, unsigned int type, const struct ConfigSetType *cst);
 bool             cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], int flags);
 struct HashElem *cs_inherit_variable(const struct ConfigSet *cs, struct HashElem *parent, const char *name);
+void             cs_uninherit_variable(const struct ConfigSet *cs, const char *name);
 
 void cs_notify_observers(const struct ConfigSet *cs, struct HashElem *he, const char *name, enum NotifyConfig ev);
 
diff --git a/config/subset.c b/config/subset.c
new file mode 100644 (file)
index 0000000..072e54c
--- /dev/null
@@ -0,0 +1,240 @@
+/**
+ * @file
+ * Subset of config items
+ *
+ * @authors
+ * Copyright (C) 2019 Richard Russon <rich@flatcap.org>
+ *
+ * @copyright
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @page config_subset Subset of config items
+ *
+ * Subset of config items
+ */
+
+#include "config.h"
+#include <stddef.h>
+#include <limits.h>
+#include <stdint.h>
+#include "mutt/mutt.h"
+#include "config/lib.h"
+#include "subset.h"
+#include "set.h"
+#include "types.h"
+
+/**
+ * cs_subset_free - Free a Config Subset
+ * @param ptr Subset to free
+ *
+ * @note Config items matching this Subset will be freed
+ */
+void cs_subset_free(struct ConfigSubset **ptr)
+{
+  if (!ptr || !*ptr)
+    return;
+
+  struct ConfigSubset *sub = *ptr;
+
+  if (sub->name)
+  {
+    char scope[256];
+    if (sub->parent && sub->parent->name)
+      snprintf(scope, sizeof(scope), "%s:%s:", sub->parent->name, sub->name);
+    else
+      snprintf(scope, sizeof(scope), "%s:", sub->name);
+
+    // We don't know if any config items have been set,
+    // so search for anything with a matching scope.
+    struct HashElem **list = get_elem_list(sub->cs);
+    for (size_t i = 0; list[i]; i++)
+    {
+      const char *item = list[i]->key.strkey;
+      if (mutt_str_startswith(item, scope, CASE_MATCH) != 0)
+      {
+        cs_uninherit_variable(sub->cs, item);
+      }
+    }
+    FREE(&list);
+  }
+
+  FREE(&sub->name);
+  FREE(ptr);
+}
+
+/**
+ * cs_subset_new - Create a new Config Subset
+ * @param name   Name for this Subset
+ * @param parent Parent Subset
+ * @retval ptr New Subset
+ *
+ * @note The name will be combined with the parent's names
+ */
+struct ConfigSubset *cs_subset_new(const char *name, struct ConfigSubset *parent)
+{
+  struct ConfigSubset *sub = mutt_mem_calloc(1, sizeof(*sub));
+
+  if (parent)
+  {
+    sub->parent = parent;
+    sub->cs = parent->cs;
+  }
+
+  if (name)
+  {
+    char scope[256];
+
+    if (parent && parent->name)
+      snprintf(scope, sizeof(scope), "%s:%s", parent->name, name);
+    else
+      mutt_str_strfcpy(scope, name, sizeof(scope));
+
+    sub->name = mutt_str_strdup(scope);
+  }
+
+  return sub;
+}
+
+/**
+ * cs_subset_lookup - Find an inherited config item
+ * @param sub  Subset to search
+ * @param name Name of Config item to find
+ * @retval ptr HashElem of the config item
+ */
+struct HashElem *cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
+{
+  if (!sub || !name)
+    return NULL;
+
+  char scope[256];
+  if (sub->name)
+    snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
+  else
+    mutt_str_strfcpy(scope, name, sizeof(scope));
+
+  return cs_get_elem(sub->cs, scope);
+}
+
+/**
+ * cs_subset_native_get - Natively get the value of an inherited config item
+ * @param sub Config Subset
+ * @param he  HashElem representing config item
+ * @param err Buffer for error messages
+ * @retval intptr_t Native pointer/value
+ * @retval INT_MIN  Error
+ */
+intptr_t cs_subset_native_get(const struct ConfigSubset *sub,
+                              struct HashElem *he, struct Buffer *err)
+{
+  if (!sub || !he)
+    return INT_MIN;
+
+  return cs_he_native_get(sub->cs, he, err);
+}
+
+/**
+ * cs_subset_native_set - Natively set the value of an inherited config item
+ * @param sub   Config Subset
+ * @param he    HashElem representing config item
+ * @param value Native pointer/value to set
+ * @param err   Buffer for error messages
+ * @retval num Result, e.g. #CSR_SUCCESS
+ */
+int cs_subset_native_set(const struct ConfigSubset *sub, struct HashElem *he,
+                         intptr_t value, struct Buffer *err)
+{
+  if (!sub || !he)
+    return CSR_ERR_CODE;
+
+  return cs_he_native_set(sub->cs, he, value, err);
+}
+
+/**
+ * cs_subset_reset - Reset an inherited config item to its parent value
+ * @param sub  Config Subset
+ * @param he   HashElem representing config item
+ * @param err  Buffer for error messages
+ * @retval num Result, e.g. #CSR_SUCCESS
+ */
+int cs_subset_reset(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
+{
+  if (!sub || !he)
+    return CSR_ERR_CODE;
+
+  return cs_he_reset(sub->cs, he, err);
+}
+
+/**
+ * cs_subset_string_get - Get an inherited config item as a string
+ * @param sub    Config Subset
+ * @param he     HashElem representing config item
+ * @param result Buffer for results or error messages
+ * @retval num Result, e.g. #CSR_SUCCESS
+ */
+int cs_subset_string_get(const struct ConfigSubset *sub, struct HashElem *he,
+                         struct Buffer *result)
+{
+  if (!sub || !he)
+    return CSR_ERR_CODE;
+
+  return cs_he_string_get(sub->cs, he, result);
+}
+
+/**
+ * cs_subset_string_set - Set an inherited config item by string
+ * @param sub   Config Subset
+ * @param he    HashElem representing config item
+ * @param value Value to set
+ * @param err   Buffer for error messages
+ * @retval num Result, e.g. #CSR_SUCCESS
+ */
+int cs_subset_string_set(const struct ConfigSubset *sub, struct HashElem *he,
+                         const char *value, struct Buffer *err)
+{
+  if (!sub || !he)
+    return INT_MIN;
+
+  return cs_he_string_set(sub->cs, he, value, err);
+}
+
+/**
+ * cs_subset_create_var - Create an inherited config item
+ * @param sub  Config Subset
+ * @param name Name of Config item to create
+ * @param err  Buffer for error messages
+ * @retval ptr HashElem of the config item
+ */
+struct HashElem *cs_subset_create_var(const struct ConfigSubset *sub,
+                                      const char *name, struct Buffer *err)
+{
+  if (!sub || !name)
+    return NULL;
+
+  // Check if name already exists
+  struct HashElem *he = cs_subset_lookup(sub, name);
+  if (he)
+    return he;
+
+  // Create parent before creating name
+  he = cs_subset_create_var(sub->parent, name, err);
+  if (!he)
+    return NULL;
+
+  char scope[256];
+  snprintf(scope, sizeof(scope), "%s:%s", sub->name, name);
+
+  return cs_inherit_variable(sub->cs, he, scope);
+}
diff --git a/config/subset.h b/config/subset.h
new file mode 100644 (file)
index 0000000..5a03adc
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * @file
+ * Subset of Config Items
+ *
+ * @authors
+ * Copyright (C) 2019 Richard Russon <rich@flatcap.org>
+ *
+ * @copyright
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUTT_CONFIG_SUBSET_H
+#define MUTT_CONFIG_SUBSET_H
+
+#include <stdio.h>
+#include "set.h"
+
+/**
+ * struct ConfigSubset - A set of inherited config items
+ */
+struct ConfigSubset
+{
+  char *name;                  ///< Scope name of Subset
+  struct ConfigSubset *parent; ///< Parent Subset
+  struct ConfigSet *cs;        ///< Parent ConfigSet
+};
+
+struct ConfigSubset *cs_subset_new       (const char *name, struct ConfigSubset *parent);
+void                 cs_subset_free      (struct ConfigSubset **ptr);
+struct HashElem *    cs_subset_lookup    (const struct ConfigSubset *sub, const char *name);
+struct HashElem *    cs_subset_create_var(const struct ConfigSubset *sub, const char *name, struct Buffer *err);
+
+intptr_t             cs_subset_native_get(const struct ConfigSubset *sub, struct HashElem *he,                    struct Buffer *err);
+int                  cs_subset_native_set(const struct ConfigSubset *sub, struct HashElem *he, intptr_t value,    struct Buffer *err);
+int                  cs_subset_reset     (const struct ConfigSubset *sub, struct HashElem *he,                    struct Buffer *err);
+int                  cs_subset_string_get(const struct ConfigSubset *sub, struct HashElem *he,                    struct Buffer *result);
+int                  cs_subset_string_set(const struct ConfigSubset *sub, struct HashElem *he, const char *value, struct Buffer *err);
+
+#endif /* MUTT_CONFIG_SUBSET_H */
index 96606718e5724b32055ede8d7cd7a205c85b1be0..5b7e0680535910ffe3fcc642d7b5756ac3e7f931 100644 (file)
@@ -48,6 +48,8 @@
 #define DT_SENSITIVE     (1 << 9)  ///< Contains sensitive value, e.g. password
 #define DT_PATH          (1 << 10) ///< A pathname
 #define DT_COMMAND       (1 << 11) ///< A command
+#define DT_INHERIT_ACC   (1 << 12) ///< Config item can be Account-specific
+#define DT_INHERIT_MBOX  (1 << 13) ///< Config item can be Mailbox-specific
 
 #define IS_SENSITIVE(x) (((x).type & DT_SENSITIVE) == DT_SENSITIVE)
 #define IS_PATH(x)      (((x)->type & (DT_STRING | DT_PATH)) == (DT_STRING | DT_PATH))