[misc] Add vsc_list_take() function that removes an item but doesn't free it.
authorMatthias Bolte <matthias.bolte@googlemail.com>
Sun, 10 May 2009 19:15:22 +0000 (21:15 +0200)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Sun, 10 May 2009 19:15:22 +0000 (21:15 +0200)
Signed-off-by: Matthias Bolte <matthias.bolte@googlemail.com>

include/libvscmisc/list.h
misc/list.c

index f07b751..9720213 100644 (file)
@@ -51,7 +51,10 @@ struct VscList * /* item */
 vsc_list_lookup (const struct VscList *list,
                  VscList_MatchFunction match_function, void *match_data);
 
-void
+struct VscList * /* item_next */
+vsc_list_take (struct VscList **list, struct VscList *item);
+
+struct VscList * /* item_next */
 vsc_list_remove (struct VscList **list, struct VscList *item,
                  VscList_FreeFunction free_function);
 
index a1ea04e..287cd26 100644 (file)
@@ -69,7 +69,7 @@ vsc_list_append (struct VscList **list, struct VscList *item)
  *
  * The list takes ownership of the appended clone.
  *
- * If an error occurs then the list is untouched.
+ * If an error occurs then the list is unchanged.
  */
 void
 vsc_list_append_clone (struct VscError *error, struct VscList **list,
@@ -151,13 +151,59 @@ vsc_list_lookup (const struct VscList *list,
 }
 
 /*!
+ * @brief Removes the item from the list without freeing it.
+ *
+ * Retruns the next item in the list if any, NULL otherwise.
+ *
+ * If the list becomes empty then the pointer to the list is set to NULL.
+ *
+ * If the item is not in the list then the list is unchanged and NULL is
+ * returned.
+ */
+struct VscList * /* item_next */
+vsc_list_take (struct VscList **list, struct VscList *item)
+{
+       struct VscList *previous_item = NULL;
+       struct VscList *current_item = NULL;
+
+       VSC__ASSERT (list != NULL);
+       VSC__ASSERT (item != NULL);
+
+       for (current_item = *list; current_item != NULL;
+            current_item = current_item->next) {
+               if (current_item == item) {
+                       if (previous_item != NULL) {
+                               previous_item->next = current_item->next;
+                               current_item->next = NULL;
+
+                               return previous_item->next;
+                       } else {
+                               *list = current_item->next;
+                               current_item->next = NULL;
+
+                               return *list;
+                       }
+               }
+
+               previous_item = current_item;
+       }
+
+       return NULL;
+}
+
+/*!
  * @brief Removes the item from the list and frees it.
  *
+ * Retruns the next item in the list if any, NULL otherwise.
+ *
  * If the list becomes empty then the pointer to the list is set to NULL.
  *
- * If the item is not in the list then the list is untouched.
+ * If the item is not in the list then the list is unchanged and NULL is
+ * returned.
+ *
+ * @note The item is only freed if it's contained in the list.
  */
-void
+struct VscList * /* item_next */
 vsc_list_remove (struct VscList **list, struct VscList *item,
                  VscList_FreeFunction free_function)
 {
@@ -177,19 +223,21 @@ vsc_list_remove (struct VscList **list, struct VscList *item,
 
                                free_function (&current_item);
 
-                               return;
+                               return previous_item->next;
                        } else {
                                *list = current_item->next;
                                current_item->next = NULL;
 
                                free_function (&current_item);
 
-                               return;
+                               return *list;
                        }
                }
 
                previous_item = current_item;
        }
+
+       return NULL;
 }
 
 /*!