]> mj.ucw.cz Git - libucw.git/commitdiff
Doc: Partially documented linked lists.
authorPavel Charvat <pchar@ucw.cz>
Thu, 6 Nov 2008 13:36:36 +0000 (14:36 +0100)
committerPavel Charvat <pchar@ucw.cz>
Thu, 6 Nov 2008 13:36:36 +0000 (14:36 +0100)
ucw/clists.h
ucw/doc/Makefile
ucw/doc/index.txt
ucw/doc/lists.txt [new file with mode: 0644]
ucw/slists.c
ucw/slists.h

index 921b7dc571ff4290717b3b09c5a4f449bf174caf..bc8779d9d9e764ba7cbc4de9dd3cfd8f95782c7a 100644 (file)
 #ifndef _UCW_CLISTS_H
 #define _UCW_CLISTS_H
 
+/**
+ * Common header for list nodes.
+ **/
 typedef struct cnode {
   struct cnode *next, *prev;
 } cnode;
 
+/**
+ * Circilar linked list.
+ **/
 typedef struct clist {
   struct cnode head;
 } clist;
 
+/**
+ * Initialize a new circular linked list. Must be called before any other function.
+ **/
+static inline void clist_init(clist *l)
+{
+  cnode *head = &l->head;
+  head->next = head->prev = head;
+}
+
+/**
+ * Return the first node on @l or NULL if @l is empty.
+ **/
 static inline void *clist_head(clist *l)
 {
   return (l->head.next != &l->head) ? l->head.next : NULL;
 }
 
+/**
+ * Return the last node on @l or NULL if @l is empty.
+ **/
 static inline void *clist_tail(clist *l)
 {
   return (l->head.prev != &l->head) ? l->head.prev : NULL;
 }
 
+/**
+ * Find the next node to @n or NULL if @n is the last one.
+ **/
 static inline void *clist_next(clist *l, cnode *n)
 {
   return (n->next != &l->head) ? (void *) n->next : NULL;
 }
 
+/**
+ * Find the previous node to @n or NULL if @n is the first one.
+ **/
 static inline void *clist_prev(clist *l, cnode *n)
 {
   return (n->prev != &l->head) ? (void *) n->prev : NULL;
 }
 
+/**
+ * Return a non-zero value iff @l is empty.
+ **/
 static inline int clist_empty(clist *l)
 {
   return (l->head.next == &l->head);
@@ -50,6 +80,9 @@ static inline int clist_empty(clist *l)
 
 #define CLIST_FOR_EACH_BACKWARDS(type,n,list) for(type n=(void*)(list).head.prev; (cnode*)(n) != &(list).head; n=(void*)((cnode*)(n))->prev)
 
+/**
+ * Insert a new node just after the node @after. To insert a new head, use @clist_add_head() instead.
+ **/
 static inline void clist_insert_after(cnode *what, cnode *after)
 {
   cnode *before = after->next;
@@ -59,6 +92,9 @@ static inline void clist_insert_after(cnode *what, cnode *after)
   after->next = what;
 }
 
+/**
+ * Insert a new node just before the node @before. To insert a new tail, use @clist_add_tail() instead.
+ **/
 static inline void clist_insert_before(cnode *what, cnode *before)
 {
   cnode *after = before->prev;
@@ -68,16 +104,25 @@ static inline void clist_insert_before(cnode *what, cnode *before)
   after->next = what;
 }
 
-static inline void clist_add_tail(clist *l, cnode *n)
+/**
+ * Insert a new node in front of all other nodes.
+ **/
+static inline void clist_add_head(clist *l, cnode *n)
 {
-  clist_insert_before(n, &l->head);
+  clist_insert_after(n, &l->head);
 }
 
-static inline void clist_add_head(clist *l, cnode *n)
+/**
+ * Insert a new node after all other nodes.
+ **/
+static inline void clist_add_tail(clist *l, cnode *n)
 {
-  clist_insert_after(n, &l->head);
+  clist_insert_before(n, &l->head);
 }
 
+/**
+ * Remove node @n.
+ **/
 static inline void clist_remove(cnode *n)
 {
   cnode *before = n->prev;
@@ -86,6 +131,9 @@ static inline void clist_remove(cnode *n)
   after->prev = before;
 }
 
+/**
+ * Remove the first node in @l. The list can be empty.
+ **/
 static inline void *clist_remove_head(clist *l)
 {
   cnode *n = clist_head(l);
@@ -94,6 +142,9 @@ static inline void *clist_remove_head(clist *l)
   return n;
 }
 
+/**
+ * Remove the last node in @l. The list can be empty.
+ **/
 static inline void *clist_remove_tail(clist *l)
 {
   cnode *n = clist_tail(l);
@@ -102,12 +153,10 @@ static inline void *clist_remove_tail(clist *l)
   return n;
 }
 
-static inline void clist_init(clist *l)
-{
-  cnode *head = &l->head;
-  head->next = head->prev = head;
-}
-
+/**
+ * Merge two lists by inserting the list @what just after the node @after in a different list.
+ * The first list is then cleared.
+ **/
 static inline void clist_insert_list_after(clist *what, cnode *after)
 {
   if (!clist_empty(what))
@@ -121,6 +170,9 @@ static inline void clist_insert_list_after(clist *what, cnode *after)
     }
 }
 
+/**
+ * Compute the number of nodes in @l. Beware linear time complexity.
+ **/
 static inline uns clist_size(clist *l)
 {
   uns i = 0;
index 6949eb530432ffc75050c003cad3af5a5db4f300..e805f79f1f10df5a0980e4d1f7df099c675a33f7 100644 (file)
@@ -2,7 +2,7 @@
 
 DIRS+=ucw/doc
 
-UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop generic growbuf unaligned
+UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop generic growbuf unaligned lists
 UCW_INDEX=$(o)/ucw/doc/def_index.html
 UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS)))
 
index 9bc470045a0e75515d10934f03b6356ac3651a73..e96211d0a4f256d53c2c48befad82f4c6d517869 100644 (file)
@@ -21,6 +21,7 @@ Modules
 - <<mempool:,Memory pools>>
 - <<mainloop:,Mainloop>>
 - <<unaligned:,Unaligned data>>
+- <<lists:,Link lists>>
 
 Other features
 --------------
@@ -43,10 +44,6 @@ Yet undocumented modules
   * `binheap.h`
   * `binheap-node.h`
   * `heap.h`
-- Link lists
-  * `clists.h`
-  * `simple-lists.h`
-  * `slists.h`
 - Hash tables
   * `hashtable.h`
 - Trie
diff --git a/ucw/doc/lists.txt b/ucw/doc/lists.txt
new file mode 100644 (file)
index 0000000..eb9f118
--- /dev/null
@@ -0,0 +1,26 @@
+Linked lists
+============
+
+Ucwlib defines two basic linked list structures: single-linked lists and circular linked lists.
+Both of them support insertion of any number of nodes, removal of nodes and various searches.
+Single-linked lists are a bit simplier (they especially requires smaller nodes)
+but some operations need assymptoticaly more time.
+
+Linked lists can be used very simply. We define a structure as list's handle and
+a common header in all inserted nodes. All routines then accept and return pointers
+to this handle and node headers.
+
+Single-linked lists
+-------------------
+
+!!ucw/slists.h
+
+Circular linked lists
+---------------------
+
+!!ucw/clists.h
+
+Circular linked lists of simple items
+-------------------------------------
+
+!!ucw/simple-lists.h
index 35b26850678429e73c857fada3346d178a930cd0..d1501d74823730a86fc4c5fdf5ac92209cf32656 100644 (file)
@@ -40,8 +40,11 @@ slist_insert_before(slist *l, snode *what, snode *before)
 void
 slist_remove(slist *l, snode *n)
 {
-  snode *p = slist_raw_prev(l, n);
-  slist_remove_after(l, p);
+  if (n)
+    {
+      snode *p = slist_raw_prev(l, n);
+      slist_remove_after(l, p);
+    }
 }
 
 #ifdef TEST
index b0e9f4e2c70aaf633edca0f4ae03054f35402712..bdab355d2a88842cf3c181f901f26ad0f133e624 100644 (file)
 #ifndef _UCW_SLISTS_H
 #define _UCW_SLISTS_H
 
+/**
+ * Common header for list nodes.
+ **/
 typedef struct snode {
   struct snode *next;
 } snode;
 
+/**
+ * Single-linked list.
+ **/
 typedef struct slist {
   struct snode head, *last;
 } slist;
 
+/**
+ * Initialize a new single-linked list. Must be called before any other function.
+ **/
+static inline void slist_init(slist *l)
+{
+  l->head.next = l->last = NULL;
+}
+
+/**
+ * Return the first node of @l or NULL if @l is empty.
+ **/
 static inline void *slist_head(slist *l)
 {
   return l->head.next;
 }
 
+/**
+ * Return the last node of @l or NULL if @l is empty.
+ **/
 static inline void *slist_tail(slist *l)
 {
   return l->last;
 }
 
+/**
+ * Find the next node to @n or NULL if @n is the last one.
+ **/
 static inline void *slist_next(snode *n)
 {
   return n->next;
 }
 
+/**
+ * Return a non-zero value iff @l is empty.
+ **/
 static inline int slist_empty(slist *l)
 {
   return !l->head.next;
 }
 
-#define SLIST_WALK(n,list) for(n=(void*)(list).head.next; (n); (n)=(void*)((snode*)(n))->next)
-#define SLIST_WALK_DELSAFE(n,list,prev) for((prev)=(void*)&(list).head; (n)=(void*)((snode*)prev)->next; (prev)=(((snode*)(prev))->next==(snode*)(n) ? (void*)(n) : (void*)(prev)))
-#define SLIST_FOR_EACH(type,n,list) for(type n=(void*)(list).head.next; n; n=(void*)((snode*)(n))->next)
-
-static inline void slist_insert_after(slist *l, snode *what, snode *after)
-{
-  what->next = after->next;
-  after->next = what;
-  if (!what->next)
-    l->last = what;
-}
-
+/**
+ * Insert a new node in front of all other nodes.
+ **/
 static inline void slist_add_head(slist *l, snode *n)
 {
   n->next = l->head.next;
@@ -58,6 +75,9 @@ static inline void slist_add_head(slist *l, snode *n)
     l->last = n;
 }
 
+/**
+ * Insert a new node after all other nodes.
+ **/
 static inline void slist_add_tail(slist *l, snode *n)
 {
   if (l->last)
@@ -68,23 +88,79 @@ static inline void slist_add_tail(slist *l, snode *n)
   l->last = n;
 }
 
-static inline void slist_init(slist *l)
+/**
+ * Insert a new node just after the node @after. To insert a new head, use @slist_add_head() instead.
+ **/
+static inline void slist_insert_after(slist *l, snode *what, snode *after)
 {
-  l->head.next = l->last = NULL;
+  what->next = after->next;
+  after->next = what;
+  if (!what->next)
+    l->last = what;
 }
 
+/**
+ * Quickly remove the node next to @after. The node may not exist.
+ **/
 static inline void slist_remove_after(slist *l, snode *after)
 {
   snode *n = after->next;
-  after->next = n->next;
-  if (l->last == n)
-    l->last = (after == &l->head) ? NULL : after;
+  if (n)
+    {
+      after->next = n->next;
+      if (l->last == n)
+        l->last = (after == &l->head) ? NULL : after;
+    }
+}
+
+/**
+ * Remove the first node in @l. The list can be empty.
+ **/
+static inline void slist_remove_head(slist *l)
+{
+  slist_remove_after(l, &l->head);
 }
 
+/* Loops */
+
+#define SLIST_WALK(n,list) for(n=(void*)(list).head.next; (n); (n)=(void*)((snode*)(n))->next)
+#define SLIST_WALK_DELSAFE(n,list,prev) for((prev)=(void*)&(list).head; (n)=(void*)((snode*)prev)->next; (prev)=(((snode*)(prev))->next==(snode*)(n) ? (void*)(n) : (void*)(prev)))
+#define SLIST_FOR_EACH(type,n,list) for(type n=(void*)(list).head.next; n; n=(void*)((snode*)(n))->next)
+
 /* Non-trivial functions */
 
+/**
+ * Find the previous node to @n or NULL if @n is the first one. Beware linear time complexity.
+ **/
 void *slist_prev(slist *l, snode *n);
+
+/**
+ * Insert a new node just before the node @before. To insert a new tail, use @slist_add_tail(). Beware linear time complexity.
+ **/
 void slist_insert_before(slist *l, snode *what, snode *before);
+
+/**
+ * Remove node @n. Beware linear time complexity.
+ **/
 void slist_remove(slist *l, snode *n);
 
+/**
+ * Remove the last node in @l. The list can be empty.
+ **/
+static inline void slist_remove_tail(slist *l)
+{
+  slist_remove(l, l->last);
+}
+
+/**
+ * Compute the number of nodes in @l. Beware linear time complexity.
+ **/
+static inline uns slist_size(slist *l)
+{
+  uns i = 0;
+  SLIST_FOR_EACH(snode *, n, *l)
+    i++;
+  return i;
+}
+
 #endif