Added silc_list_pop
[runtime.git] / lib / silcutil / silclist.h
index 81ea3638bd8a468c9a4501c9eb55c1e353c9932c..52454c30d7f1dd2b2ec1ab575d6d46a7b7520a2e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2007 Pekka Riikonen
+  Copyright (C) 2002 - 2008 Pekka Riikonen
 
   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
 
 */
 
-/****h* silcutil/SILC List Interface
+/****h* silcutil/List Interface
  *
  * DESCRIPTION
  *
- * Implementation of the SilcList interface.  This interface provides
- * simple linked list.  This interface does not allocate any memory.
+ * Generic list interface that can turn any structure with list pointers
+ * into a SilcList.  The interface can provide both singly and doubly linked
+ * lists.  The interface does not allocate any memory.
  *
  * SILC List is not thread-safe.  If the same list context must be used
  * in multithreaded environment concurrency control must be employed.
  *
+ * EXAMPLE
+ *
+ * struct EntryStruct {
+ *   char *dummy;
+ *   struct EntryStruct *next;        // The list member pointer
+ * };
+ *
+ * SilcList list;
+ *
+ * // Initialize list
+ * silc_list_init(list, struct EntryStruct, next);
+ *
  ***/
 
 #ifndef SILCLIST_H
 #define SILCLIST_H
 
-/****s* silcutil/SilcList/SilcList
+/****s* silcutil/SilcList
  *
  * NAME
  *
@@ -55,11 +68,11 @@ typedef struct SilcListStruct {
   unsigned int count       : 30;     /* Number of entries in the list */
 } SilcList;
 
-/****d* silcutil/SilcList/SILC_LIST_END
+/****d* silcutil/SILC_LIST_END
  *
  * NAME
  *
- *    #define SILC_LIST_END ...
+ *    #define SILC_LIST_END NULL
  *
  * DESCRIPTION
  *
@@ -71,7 +84,7 @@ typedef struct SilcListStruct {
 #define SILC_LIST_END NULL
 /***/
 
-/****f* silcutil/SilcList/silc_list_init
+/****f* silcutil/silc_list_init
  *
  * SYNOPSIS
  *
@@ -108,7 +121,7 @@ do {                                                        \
   (list).head = (list).tail = (list).current = NULL;   \
 } while(0)
 
-/****f* silcutil/SilcList/silc_list_init_prev
+/****f* silcutil/silc_list_init_prev
  *
  * SYNOPSIS
  *
@@ -148,11 +161,11 @@ do {                                                              \
   (list).head = (list).tail = (list).current = NULL;           \
 } while(0)
 
-/****f* silcutil/SilcList/silc_list_count
+/****f* silcutil/silc_list_count
  *
  * SYNOPSIS
  *
- *    #define silc_list_count(list) ...
+ *    SilcUInt32 silc_list_count(SilcList list);
  *
  * DESCRIPTION
  *
@@ -161,11 +174,11 @@ do {                                                              \
  ***/
 #define silc_list_count(list) (list).count
 
-/****f* silcutil/SilcList/silc_list_start
+/****f* silcutil/silc_list_start
  *
  * SYNOPSIS
  *
- *    #define silc_list_start(list) ...
+ *    void silc_list_start(SilcList list);
  *
  * DESCRIPTION
  *
@@ -176,11 +189,11 @@ do {                                                              \
 #define silc_list_start(list)                          \
   ((list).current = (list).head, (list).end_set = 0)
 
-/****f* silcutil/SilcList/silc_list_end
+/****f* silcutil/silc_list_end
  *
  * SYNOPSIS
  *
- *    #define silc_list_end(list) ...
+ *    void silc_list_end(SilcList list);
  *
  * DESCRIPTION
  *
@@ -202,11 +215,11 @@ do {                                                              \
 #define __silc_list_prev(list, pos)                            \
   ((void **)((unsigned char *)(pos) + (list).prev_offset))
 
-/****f* silcutil/SilcList/silc_list_add
+/****f* silcutil/silc_list_add
  *
  * SYNOPSIS
  *
- *    #define silc_list_add(list, entry) ...
+ *    void silc_list_add(SilcList list, void *entry);
  *
  * DESCRIPTION
  *
@@ -227,11 +240,11 @@ do {                                                      \
   (list).count++;                                      \
 } while(0)
 
-/****f* silcutil/SilcList/silc_list_insert
+/****f* silcutil/silc_list_insert
  *
  * SYNOPSIS
  *
- *    #define silc_list_insert(list, current, entry) ...
+ *    void silc_list_insert(SilcList list, void *current, void *entry);
  *
  * DESCRIPTION
  *
@@ -269,11 +282,11 @@ do {                                                                       \
   (list).count++;                                                       \
 } while(0)
 
-/****f* silcutil/SilcList/silc_list_del
+/****f* silcutil/silc_list_del
  *
  * SYNOPSIS
  *
- *    #define silc_list_del(list, entry) ...
+ *    void silc_list_del(SilcListlist, void *entry);
  *
  * DESCRIPTION
  *
@@ -287,7 +300,7 @@ do {                                                                        \
   for (p = &(list).head; *p; p = __silc_list_next(list, *p)) {         \
     if (*p == (entry)) {                                               \
       *p = *__silc_list_next(list, entry);                             \
-      if (*p && (list).prev_set)                                       \
+      if ((list).prev_set && *p)                                       \
         *__silc_list_prev(list, *p) = *__silc_list_prev(list, entry);  \
       if ((list).current == (entry))                                   \
         (list).current = *p;                                           \
@@ -300,11 +313,11 @@ do {                                                                      \
     (list).tail = prev;                                                        \
 } while(0)
 
-/****f* silcutil/SilcList/silc_list_get
+/****f* silcutil/silc_list_get
  *
  * SYNOPSIS
  *
- *    #define silc_list_get(list) ...
+ *    void *silc_list_get(SilcList list);
  *
  * DESCRIPTION
  *
@@ -342,4 +355,43 @@ void *__silc_list_get(SilcList *list)
   return pos;
 }
 
-#endif
+/****f* silcutil/silc_list_pop
+ *
+ * SYNOPSIS
+ *
+ *    void *silc_list_pop(SilcList list);
+ *
+ * DESCRIPTION
+ *
+ *    Pops the head of the list.  Removes the head of the list and returns
+ *    the removed head.  This will always remove the head of the list even
+ *    if silc_list_end was called.  Calling silc_list_start is not necessary.
+ *    Returns SILC_LIST_END if the list is empty.
+ *
+ ***/
+#define silc_list_pop(x) __silc_list_pop(&(x))
+static inline
+void *__silc_list_pop(SilcList *list)
+{
+  void *head, **p;
+
+  if (!list->head)
+    return NULL;
+
+  head = list->head;
+  p = &list->head;
+  *p = *__silc_list_next(*list, head);
+  if (list->prev_set && *p)
+    *__silc_list_prev(*list, *p) = *__silc_list_prev(*list, head);
+
+  if (list->current == head)
+    list->current = *p;
+  if (head == list->tail)
+    list->tail = NULL;
+
+  list->count--;
+
+  return head;
+}
+
+#endif /* SILCLIST_H */