]> granicus.if.org Git - neomutt/commitdiff
Refactor struct HelpList to be a Generic Vector
authorshadofren <xxlaguna93@gmail.com>
Thu, 11 Jul 2019 17:52:05 +0000 (01:52 +0800)
committerRichard Russon <rich@flatcap.org>
Mon, 21 Oct 2019 18:54:46 +0000 (19:54 +0100)
The chunks of code for Generic Vector are moved out of help.c
into vector.c. Rename struct HelpList to Vector and provide a header file for
method signature.

Makefile.autosetup
help/help.c
help/help.h
help/vector.c [new file with mode: 0644]
help/vector.h [new file with mode: 0644]

index 8746db874ab381be5cf48a570eb8a662cc97a0c8..7924b1394cc03797a25b25d417fdae755b7a2010 100644 (file)
@@ -169,7 +169,7 @@ ALLOBJS+=   $(LIBNCRYPTOBJS)
 # libhelp
 @if USE_DEVEL_HELP
 LIBHELP=       libhelp.a
-LIBHELPOBJS=   help/help.o
+LIBHELPOBJS=   help/help.o help/vector.o
 CLEANFILES+=   $(LIBHELP) $(LIBHELPOBJS)
 MUTTLIBS+=     $(LIBHELP)
 ALLOBJS+=      $(LIBHELPOBJS)
index 43f0d1c12d814980e34653ec5eb950d1736dce98..5f1faf760d67078a7d841b0a19c41b9b8f3e9b5d 100644 (file)
@@ -45,6 +45,7 @@
 #include "mutt_thread.h"
 #include "muttlib.h"
 #include "mx.h"
+#include "vector.h"
 
 struct stat;
 
@@ -57,148 +58,7 @@ struct stat;
 
 static bool __Backup_HTS; ///< used to restore $hide_thread_subject on help_mbox_close()
 static char DocDirID[33]; ///< MD5 checksum of current $help_doc_dir DT_PATH option
-static struct HelpList *DocList; ///< all valid help documents within $help_doc_dir folder
-
-/**
- * help_list_free - Free a list of Help documents
- * @param list      List to free
- * @param item_free Function to free the list contents
- */
-static void help_list_free(struct HelpList **list, void (*item_free)(void **))
-{
-  if (!list || !*list)
-    return;
-
-  for (size_t i = 0; i < (*list)->size; i++)
-  {
-    item_free(&((*list)->data[i]));
-  }
-  FREE(&(*list)->data);
-  FREE(list);
-}
-
-/**
- * help_list_shrink - Resize a List of Help documents to save space
- * @param list List to resize
- */
-static void help_list_shrink(struct HelpList *list)
-{
-  if (!list)
-    return;
-
-  mutt_mem_realloc(list->data, list->size * list->item_size);
-  list->capa = list->size;
-}
-
-/**
- * help_list_new - Create a new list of Help documents
- * @param item_size Size of items in list
- * @retval ptr New Help list
- */
-static struct HelpList *help_list_new(size_t item_size)
-{
-  struct HelpList *list = NULL;
-  if (item_size == 0)
-    return NULL;
-
-  list = mutt_mem_malloc(sizeof(struct HelpList));
-  list->item_size = item_size;
-  list->size = 0;
-  list->capa = HELPLIST_INIT_CAPACITY;
-  list->data = mutt_mem_calloc(list->capa, sizeof(void *) * list->item_size);
-
-  return list;
-}
-
-/**
- * help_list_append - Add an item to the Help document list
- * @param list List to add to
- * @param item Item to add
- */
-static void help_list_append(struct HelpList *list, void *item)
-{
-  if (!list || !item)
-    return;
-
-  if (list->size >= list->capa)
-  {
-    list->capa = (list->capa == 0) ? HELPLIST_INIT_CAPACITY : (list->capa * 2);
-    mutt_mem_realloc(list->data, list->capa * list->item_size);
-  }
-
-  list->data[list->size] = mutt_mem_calloc(1, list->item_size);
-  list->data[list->size] = item;
-  list->size++;
-}
-
-/**
- * help_list_new_append - Append a new item to a Help document list
- * @param list      List to append to
- * @param item_size Size of item to add
- * @param item      Item to add to list
- */
-static void help_list_new_append(struct HelpList **list, size_t item_size, void *item)
-{
-  if ((item_size == 0) || !item)
-    return;
-
-  if (!list || !*list)
-    *list = help_list_new(item_size);
-
-  help_list_append(*list, item);
-}
-
-/**
- * help_list_get - Get an item from a Help document list
- * @param list  List to use
- * @param index Index in list
- * @param copy  Function to copy item (may be NULL)
- * @retval ptr  Item selected
- * @retval NULL Invalid index
- */
-static void *help_list_get(struct HelpList *list, size_t index, void *(*copy)(const void *) )
-{
-  if (!list || (index >= list->size))
-    return NULL;
-
-  return ((copy) ? copy(list->data[index]) : list->data[index]);
-}
-
-/**
- * help_list_clone - Copy a list of Help documents
- * @param list   List to copy
- * @param shrink true if the list should be minimised
- * @param copy   Function to copy a list item
- * @retval ptr Duplicated list of Help documents
- */
-static struct HelpList *help_list_clone(struct HelpList *list, bool shrink,
-                                        void *(*copy)(const void *) )
-{
-  if (!list)
-    return NULL;
-
-  struct HelpList *clone = help_list_new(list->item_size);
-  for (size_t i = 0; i < list->size; i++)
-    help_list_append(clone, help_list_get(list, i, copy));
-
-  if (shrink)
-    help_list_shrink(clone);
-
-  return clone;
-}
-
-/**
- * help_list_sort - Sort a list of Help documents
- * @param list    List to sort
- * @param compare Function to compare two items
- */
-static void help_list_sort(struct HelpList *list, int (*compare)(const void *, const void *))
-{
-  if (!list)
-    return;
-
-  qsort(list->data, list->size, sizeof(void *), compare);
-}
+static struct Vector *DocList; ///< all valid help documents within $help_doc_dir folder
 
 /**
  * help_doc_type_cmp - Compare two help documents by their name - Implements ::sort_t
@@ -242,7 +102,7 @@ static void help_doc_meta_free(void **data)
   struct HelpDocMeta *meta = *data;
 
   FREE(&meta->name);
-  help_list_free(&meta->fhdr, help_file_hdr_free);
+  vector_free(&meta->fhdr, help_file_hdr_free);
   *data = NULL;
 }
 
@@ -263,7 +123,7 @@ static void help_doc_free(void **item)
  */
 void help_doclist_free(void)
 {
-  help_list_free(&DocList, help_doc_free);
+  vector_free(&DocList, help_doc_free);
   mutt_str_strfcpy(DocDirID, "", sizeof(DocDirID));
 }
 
@@ -362,7 +222,7 @@ static HelpDocFlags help_file_type(const char *file)
  * @retval -3     found invalid header: no triple-dashed start mark
  * @retval -4     found invalid header: no triple-dashed end mark
  */
-static int help_file_header(struct HelpList **fhdr, const char *file, int max)
+static int help_file_header(struct Vector **fhdr, const char *file, int max)
 {
   const char *bfn = mutt_path_basename(NONULL(file));
   const char *ext = strrchr(bfn, '.');
@@ -384,7 +244,7 @@ static int help_file_header(struct HelpList **fhdr, const char *file, int max)
     return -3;
   }
 
-  struct HelpList *list = NULL;
+  struct Vector *list = NULL;
   char *q = NULL;
   bool endmark = false;
   int count = 0;
@@ -402,7 +262,7 @@ static int help_file_header(struct HelpList **fhdr, const char *file, int max)
     struct HelpFileHeader *item = mutt_mem_calloc(1, sizeof(struct HelpFileHeader));
     item->key = mutt_str_substr_dup(p, q);
     item->val = mutt_str_strdup(mutt_str_skip_whitespace(NONULL(++q)));
-    help_list_new_append(&list, sizeof(struct HelpFileHeader), item);
+    vector_new_append(&list, sizeof(struct HelpFileHeader), item);
 
     count++;
     limit--;
@@ -412,12 +272,12 @@ static int help_file_header(struct HelpList **fhdr, const char *file, int max)
 
   if (!endmark)
   {
-    help_list_free(&list, help_file_hdr_free);
+    vector_free(&list, help_file_hdr_free);
     count = -4;
   }
   else
   {
-    help_list_shrink(list);
+    vector_shrink(list);
     *fhdr = list;
   }
 
@@ -431,7 +291,7 @@ static int help_file_header(struct HelpList **fhdr, const char *file, int max)
  * @retval ptr  Success, struct containing the found key
  * @retval NULL Failure, or when key could not be found
  */
-static struct HelpFileHeader *help_file_hdr_find(const char *key, const struct HelpList *fhdr)
+static struct HelpFileHeader *help_file_hdr_find(const char *key, const struct Vector *fhdr)
 {
   if (!fhdr || !key || !*key)
     return NULL;
@@ -489,7 +349,7 @@ static char *help_doc_msg_id(const struct tm *tm)
  *        parameter MUST be NULL currently or weird things happens when count of
  *        placeholder in strfmt and specified keys differs.
  */
-static char *help_doc_subject(struct HelpList *fhdr, const char *defsubj,
+static char *help_doc_subject(struct Vector *fhdr, const char *defsubj,
                               const char *strfmt, const char *key, ...)
 {
   va_list ap;
@@ -622,7 +482,7 @@ static void *help_doc_meta_clone(const void *item)
   struct HelpDocMeta *src = (struct HelpDocMeta *) item;
   struct HelpDocMeta *dup = mutt_mem_calloc(1, sizeof(struct HelpDocMeta));
 
-  dup->fhdr = help_list_clone(src->fhdr, true, help_file_hdr_clone);
+  dup->fhdr = vector_clone(src->fhdr, true, help_file_hdr_clone);
   dup->name = mutt_str_strdup(src->name);
   dup->type = src->type;
 
@@ -700,7 +560,7 @@ static struct Email *help_doc_from(const char *file)
   if (type == HELP_DOC_UNKNOWN)
     return NULL; /* file is not a valid help doc */
 
-  struct HelpList *fhdr = NULL;
+  struct Vector *fhdr = NULL;
   int len = help_file_header(&fhdr, file, HELP_FHDR_MAXLINES);
   if (!fhdr || (len < 1))
     return NULL; /* invalid or empty file header */
@@ -761,10 +621,10 @@ static struct Email *help_doc_from(const char *file)
  * @retval  (N!=0) Failure, (not used currently, failures are externally
  *                 checked and silently suppressed herein)
  */
-static int help_doc_gather(struct HelpList **list, const char *path)
+static int help_doc_gather(struct Vector **list, const char *path)
 {
   mutt_debug(1, "entering help_doc_gather: '%s'\n", path);
-  help_list_new_append(list, sizeof(struct Email *), help_doc_from(path));
+  vector_new_append(list, sizeof(struct Email *), help_doc_from(path));
 
   return 0;
 }
@@ -826,7 +686,7 @@ static int help_read_dir(const char *path)
     return 1;
   }
   /* Sort 'index.md' in list to the top */
-  help_list_sort(DocList, help_doc_type_cmp);
+  vector_sort(DocList, help_doc_type_cmp);
 
   struct Email *help_msg_cur = NULL;
   // All email at level 1 (directly under root will use uplinks[0] => index.md, at level n will use uplinks[n-1])
@@ -835,12 +695,12 @@ static int help_read_dir(const char *path)
   struct Email *help_msg_index = NULL;
 
   if (DocList->size > 0)
-    help_msg_index = help_list_get(DocList, 0, NULL);
+    help_msg_index = vector_get(DocList, 0, NULL);
 
   /* link all docs except the index.md (top element) */
   for (size_t i = 1; i < DocList->size; i++)
   {
-    help_msg_cur = help_list_get(DocList, i, NULL);
+    help_msg_cur = vector_get(DocList, i, NULL);
 
     int level = 1;
     char *msg_path = help_msg_cur->path;
@@ -859,7 +719,7 @@ static int help_read_dir(const char *path)
       mutt_mem_realloc(uplinks, list_size * sizeof(size_t));
     }
 
-    struct Email *help_msg_uplink = help_list_get(DocList, uplink_index, NULL);
+    struct Email *help_msg_uplink = vector_get(DocList, uplink_index, NULL);
     mutt_debug(5, "Uplinking '%s' to '%s'\n", path, help_msg_uplink->path);
     help_doc_uplink(help_msg_uplink, help_msg_cur);
     help_msg_cur->index = i;
@@ -888,7 +748,7 @@ int help_doclist_init(void)
     return 0;
 
   help_doclist_free();
-  DocList = help_list_new(sizeof(struct Email));
+  DocList = vector_new(sizeof(struct Email));
   help_read_dir(C_HelpDocDir);
   help_docdir_id(C_HelpDocDir);
   return 0;
@@ -910,7 +770,7 @@ static int help_doclist_parse(struct Mailbox *m)
   if ((help_doclist_init() != 0) || (DocList->size == 0))
     return -1;
 
-  m->emails = (struct Email **) (help_list_clone(DocList, true, help_doc_clone))->data;
+  m->emails = (struct Email **) (vector_clone(DocList, true, help_doc_clone))->data;
   m->msg_count = m->email_max = DocList->size;
   mutt_mem_realloc(&m->v2r, sizeof(int) * m->email_max);
 
index 9278b0e7432a78857cf9f74a3764356b9b7597f4..0abcde3987bb853d1c44d9bf6a517db9508ab3ff 100644 (file)
@@ -28,6 +28,7 @@
 #include <stddef.h>
 #include <stdint.h>
 #include "mx.h"
+#include "vector.h"
 
 extern struct MxOps MxHelpOps;
 
@@ -39,18 +40,6 @@ typedef uint8_t HelpDocFlags;     ///< Types of Help Documents, e.g. #HELP_DOC_I
 #define HELP_DOC_CHAPTER (1 << 3) ///< Document is treated as help chapter
 #define HELP_DOC_SECTION (1 << 4) ///< Document is treated as help section
 
-/**
- * struct HelpList - Generic list to hold several help elements
- */
-struct HelpList
-{
-  size_t item_size; ///< Size of a single element
-  size_t size;      ///< List length
-  size_t capa;      ///< List capacity
-  void **data;      ///< Internal list data pointers
-};
-#define HELPLIST_INIT_CAPACITY 10
-
 /**
  * struct helpfile_header - Describes the header of a help file
  */
@@ -65,7 +54,7 @@ struct HelpFileHeader
  */
 struct HelpDocMeta
 {
-  struct HelpList *fhdr; ///< File header lines (list of key/value pairs)
+  struct Vector *fhdr;   ///< File header lines (list of key/value pairs)
   char *name;            ///< Base file name
   HelpDocFlags type;     ///< Type of the help document
 };
diff --git a/help/vector.c b/help/vector.c
new file mode 100644 (file)
index 0000000..9c91349
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * @file
+ * Expandable array
+ *
+ * @authors
+ * Copyright (C) 2019 Tran Manh Tu <xxlaguna93@gmail.com>
+ *
+ * @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/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "vector.h"
+#include "mutt/mutt.h"
+
+/**
+ * vector_free - Free a list of Help documents
+ * @param list      List to free
+ * @param item_free Function to free the list contents
+ */
+void vector_free(struct Vector **list, void (*item_free)(void **))
+{
+  if (!list || !*list)
+    return;
+
+  for (size_t i = 0; i < (*list)->size; i++)
+  {
+    item_free(&((*list)->data[i]));
+  }
+  FREE(&(*list)->data);
+  FREE(list);
+}
+
+/**
+ * vector_shrink - Resize a List of Help documents to save space
+ * @param list List to resize
+ */
+void vector_shrink(struct Vector *list)
+{
+  if (!list)
+    return;
+
+  mutt_mem_realloc(list->data, list->size * list->item_size);
+  list->capa = list->size;
+}
+
+/**
+ * vector_new - Create a new list of Help documents
+ * @param item_size Size of items in list
+ * @retval ptr New Help list
+ */
+struct Vector *vector_new(size_t item_size)
+{
+  struct Vector *list = NULL;
+  if (item_size == 0)
+    return NULL;
+
+  list = mutt_mem_malloc(sizeof(struct Vector));
+  list->item_size = item_size;
+  list->size = 0;
+  list->capa = VECTOR_INIT_CAPACITY;
+  list->data = mutt_mem_calloc(list->capa, sizeof(void *) * list->item_size);
+
+  return list;
+}
+
+/**
+ * vector_append - Add an item to the Help document list
+ * @param list List to add to
+ * @param item Item to add
+ */
+void vector_append(struct Vector *list, void *item)
+{
+  if (!list || !item)
+    return;
+
+  if (list->size >= list->capa)
+  {
+    list->capa = (list->capa == 0) ? VECTOR_INIT_CAPACITY : (list->capa * 2);
+    mutt_mem_realloc(list->data, list->capa * list->item_size);
+  }
+
+  list->data[list->size] = mutt_mem_calloc(1, list->item_size);
+  list->data[list->size] = item;
+  list->size++;
+}
+
+/**
+ * vector_new_append - Append a new item to a Help document list
+ * @param list      List to append to
+ * @param item_size Size of item to add
+ * @param item      Item to add to list
+ */
+void vector_new_append(struct Vector **list, size_t item_size, void *item)
+{
+  if ((item_size == 0) || !item)
+    return;
+
+  if (!list || !*list)
+    *list = vector_new(item_size);
+
+  vector_append(*list, item);
+}
+
+/**
+ * vector_get - Get an item from a Help document list
+ * @param list  List to use
+ * @param index Index in list
+ * @param copy  Function to copy item (may be NULL)
+ * @retval ptr  Item selected
+ * @retval NULL Invalid index
+ */
+void *vector_get(struct Vector *list, size_t index, void *(*copy)(const void *) )
+{
+  if (!list || (index >= list->size))
+    return NULL;
+
+  return ((copy) ? copy(list->data[index]) : list->data[index]);
+}
+
+/**
+ * vector_clone - Copy a list of Help documents
+ * @param list   List to copy
+ * @param shrink true if the list should be minimised
+ * @param copy   Function to copy a list item
+ * @retval ptr Duplicated list of Help documents
+ */
+struct Vector *vector_clone(struct Vector *list, bool shrink, void *(*copy)(const void *) )
+{
+  if (!list)
+    return NULL;
+
+  struct Vector *clone = vector_new(list->item_size);
+  for (size_t i = 0; i < list->size; i++)
+    vector_append(clone, vector_get(list, i, copy));
+
+  if (shrink)
+    vector_shrink(clone);
+
+  return clone;
+}
+
+/**
+ * vector_sort - Sort a list of Help documents
+ * @param list    List to sort
+ * @param compare Function to compare two items
+ */
+void vector_sort(struct Vector *list, int (*compare)(const void *, const void *))
+{
+  if (!list)
+    return;
+
+  qsort(list->data, list->size, sizeof(void *), compare);
+}
diff --git a/help/vector.h b/help/vector.h
new file mode 100644 (file)
index 0000000..c85037b
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * @file
+ * Expandable array
+ *
+ * @authors
+ * Copyright (C) 2019 Tran Manh Tu <xxlaguna93@gmail.com>
+ *
+ * @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/>.
+ */
+
+#include <stdbool.h>
+
+#ifndef MUTT_HELP_VECTOR_H
+#define MUTT_HELP_VECTOR_H
+
+#define VECTOR_INIT_CAPACITY 16
+
+/**
+ * struct Vector - Generic array to hold several elements
+ */
+struct Vector
+{
+  size_t item_size; ///< Size of a single element
+  size_t size;      ///< List length
+  size_t capa;      ///< List capacity
+  void **data;      ///< Internal list data pointers
+};
+
+void           vector_append    (struct Vector *list, void *item);
+struct Vector *vector_clone     (struct Vector *list, bool shrink, void *(*copy)(const void *));
+void           vector_free      (struct Vector **list, void (*item_free)(void **));
+void *         vector_get       (struct Vector *list, size_t index, void *(*copy)(const void *));
+struct Vector *vector_new       (size_t item_size);
+void           vector_new_append(struct Vector **list, size_t item_size, void *item);
+void           vector_shrink    (struct Vector *list);
+void           vector_sort      (struct Vector *list, int (*compare)(const void *, const void *));
+
+#endif /* MUTT_HELP_VECTOR_H */