]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add proper doc comments for hash & linklist 2289/head
authorQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 24 May 2018 18:43:57 +0000 (18:43 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 25 May 2018 16:29:54 +0000 (16:29 +0000)
* Remove references to ospf source files from linklist.[ch]
* Remove documentation comments from hash.c and linklist.c
* Add comprehensive documentation comments to linklist.h and hash.h

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/hash.c
lib/hash.h
lib/linklist.c
lib/linklist.h

index 01f160f94addab3fbde429addc1c40c690db82ae..ee5401b2367a4816111439863c3b67f1d8df51d7 100644 (file)
@@ -36,7 +36,6 @@ DEFINE_MTYPE_STATIC(LIB, HASH_INDEX, "Hash Index")
 pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER;
 static struct list *_hashes;
 
-/* Allocate a new hash.  */
 struct hash *hash_create_size(unsigned int size,
                              unsigned int (*hash_key)(void *),
                              int (*hash_cmp)(const void *, const void *),
@@ -67,7 +66,6 @@ struct hash *hash_create_size(unsigned int size,
        return hash;
 }
 
-/* Allocate a new hash with default hash size.  */
 struct hash *hash_create(unsigned int (*hash_key)(void *),
                         int (*hash_cmp)(const void *, const void *),
                         const char *name)
@@ -75,9 +73,6 @@ struct hash *hash_create(unsigned int (*hash_key)(void *),
        return hash_create_size(HASH_INITIAL_SIZE, hash_key, hash_cmp, name);
 }
 
-/* Utility function for hash_get().  When this function is specified
-   as alloc_func, return arugment as it is.  This function is used for
-   intern already allocated value.  */
 void *hash_alloc_intern(void *arg)
 {
        return arg;
@@ -133,9 +128,6 @@ static void hash_expand(struct hash *hash)
        hash->index = new_index;
 }
 
-/* Lookup and return hash backet in hash.  If there is no
-   corresponding hash backet and alloc_func is specified, create new
-   hash backet.  */
 void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *))
 {
        unsigned int key;
@@ -189,13 +181,11 @@ void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *))
        return NULL;
 }
 
-/* Hash lookup.  */
 void *hash_lookup(struct hash *hash, void *data)
 {
        return hash_get(hash, data, NULL);
 }
 
-/* Simple Bernstein hash which is simple and fast for common case */
 unsigned int string_hash_make(const char *str)
 {
        unsigned int hash = 0;
@@ -206,9 +196,6 @@ unsigned int string_hash_make(const char *str)
        return hash;
 }
 
-/* This function release registered value from specified hash.  When
-   release is successfully finished, return the data pointer in the
-   hash backet.  */
 void *hash_release(struct hash *hash, void *data)
 {
        void *ret;
@@ -248,7 +235,6 @@ void *hash_release(struct hash *hash, void *data)
        return NULL;
 }
 
-/* Iterator function for hash.  */
 void hash_iterate(struct hash *hash, void (*func)(struct hash_backet *, void *),
                  void *arg)
 {
@@ -266,7 +252,6 @@ void hash_iterate(struct hash *hash, void (*func)(struct hash_backet *, void *),
                }
 }
 
-/* Iterator function for hash.  */
 void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *),
               void *arg)
 {
@@ -288,7 +273,6 @@ void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *),
        }
 }
 
-/* Clean up hash.  */
 void hash_clean(struct hash *hash, void (*free_func)(void *))
 {
        unsigned int i;
@@ -327,8 +311,6 @@ struct list *hash_to_list(struct hash *hash)
        return list;
 }
 
-/* Free hash memory.  You may call hash_clean before call this
-   function.  */
 void hash_free(struct hash *hash)
 {
        pthread_mutex_lock(&_hashes_mtx);
index 2510422e219d34c60bc23d1d06d18ffeb7ea48d8..c7e670b7238affa725ae7c038d484fad5870de4c 100644 (file)
@@ -36,9 +36,10 @@ DECLARE_MTYPE(HASH_BACKET)
 #define HASHWALK_ABORT -1
 
 struct hash_backet {
-       /* if this backet is the head of the linked listed, len denotes the
-        * number of
-        * elements in the list */
+       /*
+        * if this backet is the head of the linked listed, len denotes the
+        * number of elements in the list
+        */
        int len;
 
        /* Linked list.  */
@@ -85,38 +86,232 @@ struct hash {
 
 #define hashcount(X) ((X)->count)
 
-extern struct hash *hash_create(unsigned int (*)(void *),
-                               int (*)(const void *, const void *),
-                               const char *);
-extern struct hash *hash_create_size(unsigned int, unsigned int (*)(void *),
-                                    int (*)(const void *, const void *),
-                                    const char *);
+/*
+ * Create a hash table.
+ *
+ * The created hash table uses chaining and a user-provided comparator function
+ * to resolve collisions. For best performance use a perfect hash function.
+ * Worst case lookup time is O(N) when using a constant hash function. Best
+ * case lookup time is O(1) when using a perfect hash function.
+ *
+ * The initial size of the created hash table is HASH_INITIAL_SIZE.
+ *
+ * hash_key
+ *    hash function to use; should return a unique unsigned integer when called
+ *    with a data item. Collisions are acceptable.
+ *
+ * hash_cmp
+ *    comparison function used for resolving collisions; when called with two
+ *    data items, should return nonzero if the two items are equal and 0
+ *    otherwise
+ *
+ * name
+ *    optional name for the hashtable; this is used when displaying global
+ *    hashtable statistics. If this parameter is NULL the hash's name will be
+ *    set to NULL and the default name will be displayed when showing
+ *    statistics.
+ *
+ * Returns:
+ *    a new hash table
+ */
+extern struct hash *hash_create(unsigned int (*hash_key)(void *),
+                               int (*hash_cmp)(const void *, const void *),
+                               const char *name);
+
+/*
+ * Create a hash table.
+ *
+ * The created hash table uses chaining and a user-provided comparator function
+ * to resolve collisions. For best performance use a perfect hash function.
+ * Worst case lookup time is O(N) when using a constant hash function. Best
+ * case lookup time is O(1) when using a perfect hash function.
+ *
+ * size
+ *    initial number of hash buckets to allocate; must be a power of 2 or the
+ *    program will assert
+ *
+ * hash_key
+ *    hash function to use; should return a unique unsigned integer when called
+ *    with a data item. Collisions are acceptable.
+ *
+ * hash_cmp
+ *    comparison function used for resolving collisions; when called with two
+ *    data items, should return nonzero if the two items are equal and 0
+ *    otherwise
+ *
+ * name
+ *    optional name for the hashtable; this is used when displaying global
+ *    hashtable statistics. If this parameter is NULL the hash's name will be
+ *    set to NULL and the default name will be displayed when showing
+ *    statistics.
+ *
+ * Returns:
+ *    a new hash table
+ */
+extern struct hash *
+hash_create_size(unsigned int size, unsigned int (*hash_key)(void *),
+                int (*hash_cmp)(const void *, const void *), const char *name);
+
+/*
+ * Retrieve or insert data from / into a hash table.
+ *
+ * This function is somewhat counterintuitive in its usage. In order to look up
+ * an element from its key, you must provide the data item itself, with the
+ * portions used in the hash function set to the same values as the data item
+ * to retrieve. To insert a data element, either provide the key as just
+ * described and provide alloc_func as descrbied below to allocate the full
+ * data element, or provide the full data element and pass 'hash_alloc_intern'
+ * to alloc_func.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data to insert or retrieve
+ *
+ * alloc_func
+ *    function to call if the item is not found in the hash table. This
+ *    function is called with the value of 'data' and should create the data
+ *    item to insert and return a pointer to it. If the data has already been
+ *    completely created and provided in the 'data' parameter, passing
+ *    'hash_alloc_intern' to this parameter will cause 'data' to be inserted.
+ *    If this parameter is NULL, then this call to hash_get is equivalent to
+ *    hash_lookup.
+ *
+ * Returns:
+ *    the data item found or inserted, or NULL if alloc_func is NULL and the
+ *    data is not found
+ */
+extern void *hash_get(struct hash *hash, void *data,
+                     void *(*alloc_func)(void *));
+
+/*
+ * Dummy element allocation function.
+ *
+ * See hash_get for details.
+ *
+ * data
+ *    data to insert into the hash table
+ *
+ * Returns:
+ *    data
+ */
+extern void *hash_alloc_intern(void *data);
+
+/*
+ * Retrieve an item from a hash table.
+ *
+ * This function is equivalent to calling hash_get with alloc_func set to NULL.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data element with values used for key computation set
+ *
+ * Returns:
+ *    the data element if found, or NULL if not found
+ */
+extern void *hash_lookup(struct hash *hash, void *data);
 
-extern void *hash_get(struct hash *, void *, void *(*)(void *));
-extern void *hash_alloc_intern(void *);
-extern void *hash_lookup(struct hash *, void *);
-extern void *hash_release(struct hash *, void *);
+/*
+ * Remove an element from a hash table.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * data
+ *    data element to remove with values used for key computation set
+ *
+ * Returns:
+ *    the removed element if found, or NULL if not found
+ */
+extern void *hash_release(struct hash *hash, void *data);
 
-extern void hash_iterate(struct hash *, void (*)(struct hash_backet *, void *),
-                        void *);
+/*
+ * Iterate over the elements in a hash table.
+ *
+ * It is safe to delete items passed to the iteration function from the hash
+ * table during iteration.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * func
+ *    function to call with each data item
+ *
+ * arg
+ *    arbitrary argument passed as the second parameter in each call to 'func'
+ */
+extern void hash_iterate(struct hash *hash,
+                        void (*func)(struct hash_backet *, void *), void *arg);
 
-extern void hash_walk(struct hash *, int (*)(struct hash_backet *, void *),
-                     void *);
+/*
+ * Iterate over the elements in a hash table, stopping on condition.
+ *
+ * It is safe to delete items passed to the iteration function from the hash
+ * table during iteration.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * func
+ *    function to call with each data item. If this function returns
+ *    HASHWALK_ABORT then the iteration stops.
+ *
+ * arg
+ *    arbitrary argument passed as the second parameter in each call to 'func'
+ */
+extern void hash_walk(struct hash *hash,
+                     int (*func)(struct hash_backet *, void *), void *arg);
 
-extern void hash_clean(struct hash *, void (*)(void *));
-extern void hash_free(struct hash *);
+/*
+ * Remove all elements from a hash table.
+ *
+ * hash
+ *    hash table to operate on
+ *
+ * free_func
+ *    function to call with each removed item; intended to free the data
+ */
+extern void hash_clean(struct hash *hash, void (*free_func)(void *));
+
+/*
+ * Delete a hash table.
+ *
+ * This function assumes the table is empty. Call hash_clean to delete the
+ * hashtable contents if necessary.
+ *
+ * hash
+ *    hash table to delete
+ */
+extern void hash_free(struct hash *hash);
 
 /*
  * Converts a hash table to an unsorted linked list.
  * Does not modify the hash table in any way.
  *
  * hash
- *    the hash to convert
+ *    hash table to convert
  */
 extern struct list *hash_to_list(struct hash *hash);
 
+/*
+ * Hash a string using the modified Bernstein hash.
+ *
+ * This is not a perfect hash function.
+ *
+ * str
+ *    string to hash
+ *
+ * Returns:
+ *    modified Bernstein hash of the string
+ */
 extern unsigned int string_hash_make(const char *);
 
+/*
+ * Install CLI commands for viewing global hash table statistics.
+ */
 extern void hash_cmd_init(void);
 
 #endif /* _ZEBRA_HASH_H */
index 3a35b250ca560b1ed533b25427c6c7a8314f3131..2cfa3e748208158968754fa14ca314593b97d867 100644 (file)
@@ -27,7 +27,6 @@
 DEFINE_MTYPE_STATIC(LIB, LINK_LIST, "Link List")
 DEFINE_MTYPE_STATIC(LIB, LINK_NODE, "Link Node")
 
-/* Allocate new list. */
 struct list *list_new(void)
 {
        return XCALLOC(MTYPE_LINK_LIST, sizeof(struct list));
@@ -51,7 +50,6 @@ static void listnode_free(struct listnode *node)
        XFREE(MTYPE_LINK_NODE, node);
 }
 
-/* Add new data to the list. */
 void listnode_add(struct list *list, void *val)
 {
        struct listnode *node;
@@ -72,12 +70,6 @@ void listnode_add(struct list *list, void *val)
        list->count++;
 }
 
-/*
- * Add a node to the list.  If the list was sorted according to the
- * cmp function, insert a new node with the given val such that the
- * list remains sorted.  The new node is always inserted; there is no
- * notion of omitting duplicates.
- */
 void listnode_add_sort(struct list *list, void *val)
 {
        struct listnode *n;
@@ -186,14 +178,12 @@ struct listnode *listnode_add_before(struct list *list, struct listnode *pp,
        return nn;
 }
 
-/* Move given listnode to tail of the list */
 void listnode_move_to_tail(struct list *l, struct listnode *n)
 {
        LISTNODE_DETACH(l, n);
        LISTNODE_ATTACH(l, n);
 }
 
-/* Delete specific date pointer from the list. */
 void listnode_delete(struct list *list, void *val)
 {
        struct listnode *node;
@@ -218,7 +208,6 @@ void listnode_delete(struct list *list, void *val)
        }
 }
 
-/* Return first node's data if it is there.  */
 void *listnode_head(struct list *list)
 {
        struct listnode *node;
@@ -231,7 +220,6 @@ void *listnode_head(struct list *list)
        return NULL;
 }
 
-/* Delete all listnode from the list. */
 void list_delete_all_node(struct list *list)
 {
        struct listnode *node;
@@ -248,7 +236,6 @@ void list_delete_all_node(struct list *list)
        list->count = 0;
 }
 
-/* Delete all listnode then free list itself. */
 void list_delete_and_null(struct list **list)
 {
        assert(*list);
@@ -262,7 +249,6 @@ void list_delete_original(struct list *list)
        list_delete_and_null(&list);
 }
 
-/* Lookup the node which has given data. */
 struct listnode *listnode_lookup(struct list *list, void *data)
 {
        struct listnode *node;
@@ -274,7 +260,6 @@ struct listnode *listnode_lookup(struct list *list, void *data)
        return NULL;
 }
 
-/* Delete the node from list.  For ospfd and ospf6d. */
 void list_delete_node(struct list *list, struct listnode *node)
 {
        if (node->prev)
@@ -289,25 +274,24 @@ void list_delete_node(struct list *list, struct listnode *node)
        listnode_free(node);
 }
 
-/* ospf_spf.c */
-void list_add_list(struct list *l, struct list *m)
+void list_add_list(struct list *list, struct list *add)
 {
        struct listnode *n;
 
-       for (n = listhead(m); n; n = listnextnode(n))
-               listnode_add(l, n->data);
+       for (n = listhead(add); n; n = listnextnode(n))
+               listnode_add(list, n->data);
 }
 
-struct list *list_dup(struct list *l)
+struct list *list_dup(struct list *list)
 {
        struct list *new = list_new();
        struct listnode *ln;
        void *data;
 
-       new->cmp = l->cmp;
-       new->del = l->del;
+       new->cmp = list->cmp;
+       new->del = list->del;
 
-       for (ALL_LIST_ELEMENTS_RO(l, ln, data))
+       for (ALL_LIST_ELEMENTS_RO(list, ln, data))
                listnode_add(new, data);
 
        return new;
index d6d9b5e087a1563aa6f70333b2bb725c84636bec..39e70293d24bafd974afaf87f5221bef01c3861a 100644 (file)
@@ -59,23 +59,166 @@ struct list {
 /* return X->data only if X and X->data are not NULL */
 #define listgetdata(X) (assert(X), assert((X)->data != NULL), (X)->data)
 
-/* Prototypes. */
-extern struct list *
-list_new(void); /* encouraged: set list.del callback on new lists */
-
-extern void listnode_add(struct list *, void *);
-extern void listnode_add_sort(struct list *, void *);
-extern struct listnode *listnode_add_after(struct list *, struct listnode *,
-                                          void *);
-extern struct listnode *listnode_add_before(struct list *, struct listnode *,
-                                           void *);
-extern void listnode_move_to_tail(struct list *, struct listnode *);
-extern void listnode_delete(struct list *, void *);
-extern struct listnode *listnode_lookup(struct list *, void *);
-extern void *listnode_head(struct list *);
+/*
+ * Create a new linked list.
+ *
+ * Returns:
+ *    the created linked list
+ */
+extern struct list *list_new(void);
+
+/*
+ * Add a new element to the tail of a list.
+ *
+ * Runtime is O(1).
+ *
+ * list
+ *    list to operate on
+ *
+ * data
+ *    element to add
+ */
+extern void listnode_add(struct list *list, void *data);
+
+/*
+ * Insert a new element into a list with insertion sort.
+ *
+ * If list->cmp is set, this function is used to determine the position to
+ * insert the new element. If it is not set, this function is equivalent to
+ * listnode_add.
+ *
+ * Runtime is O(N).
+ *
+ * list
+ *    list to operate on
+ *
+ * val
+ *    element to add
+ */
+extern void listnode_add_sort(struct list *list, void *val);
+
+/*
+ * Insert a new element into a list after another element.
+ *
+ * Runtime is O(1).
+ *
+ * list
+ *    list to operate on
+ *
+ * pp
+ *    listnode to insert after
+ *
+ * data
+ *    data to insert
+ *
+ * Returns:
+ *    pointer to newly created listnode that contains the inserted data
+ */
+extern struct listnode *listnode_add_after(struct list *list,
+                                          struct listnode *pp, void *data);
+
+/*
+ * Insert a new element into a list before another element.
+ *
+ * Runtime is O(1).
+ *
+ * list
+ *    list to operate on
+ *
+ * pp
+ *    listnode to insert before
+ *
+ * data
+ *    data to insert
+ *
+ * Returns:
+ *    pointer to newly created listnode that contains the inserted data
+ */
+extern struct listnode *listnode_add_before(struct list *list,
+                                           struct listnode *pp, void *data);
+
+/*
+ * Move a node to the tail of a list.
+ *
+ * Runtime is O(1).
+ *
+ * list
+ *    list to operate on
+ *
+ * node
+ *    node to move to tail
+ */
+extern void listnode_move_to_tail(struct list *list, struct listnode *node);
+
+/*
+ * Delete an element from a list.
+ *
+ * Runtime is O(N).
+ *
+ * list
+ *    list to operate on
+ *
+ * data
+ *    data to insert into list
+ */
+extern void listnode_delete(struct list *list, void *data);
+
+/*
+ * Find the listnode corresponding to an element in a list.
+ *
+ * list
+ *    list to operate on
+ *
+ * data
+ *    data to search for
+ *
+ * Returns:
+ *    pointer to listnode storing the given data if found, NULL otherwise
+ */
+extern struct listnode *listnode_lookup(struct list *list, void *data);
+
+/*
+ * Retrieve the element at the head of a list.
+ *
+ * list
+ *    list to operate on
+ *
+ * Returns:
+ *    data at head of list, or NULL if list is empty
+ */
+extern void *listnode_head(struct list *list);
+
+/*
+ * Duplicate a list.
+ *
+ * list
+ *    list to duplicate
+ *
+ * Returns:
+ *    copy of the list
+ */
 extern struct list *list_dup(struct list *l);
+
+/*
+ * Sort a list in place.
+ *
+ * The sorting algorithm used is quicksort. Runtimes are equivalent to those of
+ * quicksort plus N. The sort is not stable.
+ *
+ * For portability reasons, the comparison function takes a pointer to pointer
+ * to void. This pointer should be dereferenced to get the actual data pointer.
+ * It is always safe to do this.
+ *
+ * list
+ *    list to sort
+ *
+ * cmp
+ *    comparison function for quicksort. Should return less than, equal to or
+ *    greater than zero if the first argument is less than, equal to or greater
+ *    than the second argument.
+ */
 extern void list_sort(struct list *list,
-                     int (*cmp)(const void *, const void *));
+                     int (*cmp)(const void **, const void **));
 
 /*
  * The usage of list_delete is being transitioned to pass in
@@ -90,8 +233,27 @@ extern void list_sort(struct list *list,
 #if defined(VERSION_TYPE_DEV) && CONFDATE > 20181001
 CPP_NOTICE("list_delete without double pointer is deprecated, please fixup")
 #endif
-extern void list_delete_and_null(struct list **);
-extern void list_delete_original(struct list *);
+
+/*
+ * Delete a list and NULL its pointer.
+ *
+ * If non-null, list->del is called with each data element.
+ *
+ * plist
+ *    pointer to list pointer; this will be set to NULL after the list has been
+ *    deleted
+ */
+extern void list_delete_and_null(struct list **plist);
+
+/*
+ * Delete a list.
+ *
+ * If non-null, list->del is called with each data element.
+ *
+ * plist
+ *    pointer to list pointer
+ */
+extern void list_delete_original(struct list *list);
 #define list_delete(X)                                                         \
        list_delete_original((X))                                              \
                CPP_WARN("Please transition to using list_delete_and_null")
@@ -99,13 +261,43 @@ extern void list_delete_original(struct list *);
        list_delete_original((X))                                              \
                CPP_WARN("Please transition tousing list_delete_and_null")
 
-extern void list_delete_all_node(struct list *);
+/*
+ * Delete all nodes from a list without deleting the list itself.
+ *
+ * If non-null, list->del is called with each data element.
+ *
+ * list
+ *    list to operate on
+ */
+extern void list_delete_all_node(struct list *list);
 
-/* For ospfd and ospf6d. */
-extern void list_delete_node(struct list *, struct listnode *);
+/*
+ * Delete a node from a list.
+ *
+ * list->del is not called with the data associated with the node.
+ *
+ * Runtime is O(1).
+ *
+ * list
+ *    list to operate on
+ *
+ * node
+ *    the node to delete
+ */
+extern void list_delete_node(struct list *list, struct listnode *node);
 
-/* For ospf_spf.c */
-extern void list_add_list(struct list *, struct list *);
+/*
+ * Append a list to an existing list.
+ *
+ * Runtime is O(N) where N = listcount(add).
+ *
+ * list
+ *    list to append to
+ *
+ * add
+ *    list to append
+ */
+extern void list_add_list(struct list *list, struct list *add);
 
 /* List iteration macro.
  * Usage: for (ALL_LIST_ELEMENTS (...) { ... }