- add user feedback
[oweals/gnunet.git] / src / util / container_slist.c
index 715dcee323c9553f1143284a2dd075e3403cfcf3..e75c695c51e56a43082245ddcf3d1da252d1106f 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet 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, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -27,6 +27,8 @@
 #include "platform.h"
 #include "gnunet_container_lib.h"
 
 #include "platform.h"
 #include "gnunet_container_lib.h"
 
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
 /**
  * Element in our linked list.
  */
 /**
  * Element in our linked list.
  */
@@ -55,7 +57,7 @@ struct GNUNET_CONTAINER_SList_Elem
 
 
 /**
 
 
 /**
- * Handle to a singly linked list  
+ * Handle to a singly linked list
  */
 struct GNUNET_CONTAINER_SList
 {
  */
 struct GNUNET_CONTAINER_SList
 {
@@ -65,34 +67,18 @@ struct GNUNET_CONTAINER_SList
   struct GNUNET_CONTAINER_SList_Elem *head;
 
   /**
   struct GNUNET_CONTAINER_SList_Elem *head;
 
   /**
-   * Number of elements in the list.
-   */
-  unsigned int length;
-};
-
-
-/**
- * Handle to a singly linked list iterator 
- */
-struct GNUNET_CONTAINER_SList_Iterator
-{
-  /**
-   * Linked list that we are iterating over.
-   */
-  struct GNUNET_CONTAINER_SList *list;
-
-  /**
-   * Last element accessed.
+   * Tail of the linked list.
    */
    */
-  struct GNUNET_CONTAINER_SList_Elem *last;
+  struct GNUNET_CONTAINER_SList_Elem *tail;
 
   /**
 
   /**
-   * Current list element.
+   * Number of elements in the list.
    */
    */
-  struct GNUNET_CONTAINER_SList_Elem *elem;
+  unsigned int length;
 };
 
 
 };
 
 
+
 /**
  * Create a new element that is to be inserted into the list
  * @internal
 /**
  * Create a new element that is to be inserted into the list
  * @internal
@@ -102,22 +88,22 @@ struct GNUNET_CONTAINER_SList_Iterator
  * @return a new element
  */
 static struct GNUNET_CONTAINER_SList_Elem *
  * @return a new element
  */
 static struct GNUNET_CONTAINER_SList_Elem *
-create_elem (enum GNUNET_CONTAINER_SListDisposition disp,
-             const void *buf, size_t len)
+create_elem (enum GNUNET_CONTAINER_SListDisposition disp, const void *buf,
+             size_t len)
 {
   struct GNUNET_CONTAINER_SList_Elem *e;
 
   if (disp == GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT)
 {
   struct GNUNET_CONTAINER_SList_Elem *e;
 
   if (disp == GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT)
-    {
-      e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem) + len);
-      memcpy (&e[1], buf, len);
-      e->elem = (void *) &e[1];
-    }
+  {
+    e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem) + len);
+    memcpy (&e[1], buf, len);
+    e->elem = (void *) &e[1];
+  }
   else
   else
-    {
-      e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem));
-      e->elem = (void *) buf;
-    }
+  {
+    e = GNUNET_new (struct GNUNET_CONTAINER_SList_Elem);
+    e->elem = (void *) buf;
+  }
   e->disp = disp;
   e->len = len;
   return e;
   e->disp = disp;
   e->len = len;
   return e;
@@ -141,10 +127,62 @@ GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l,
   e = create_elem (disp, buf, len);
   e->next = l->head;
   l->head = e;
   e = create_elem (disp, buf, len);
   e->next = l->head;
   l->head = e;
+  if (l->tail == NULL)
+    l->tail = e;
+  l->length++;
+}
+
+/**
+ * Add a new element to the end of the list
+ * @param l list
+ * @param disp memory disposition
+ * @param buf payload buffer
+ * @param len length of the buffer
+ */
+void
+GNUNET_CONTAINER_slist_add_end (struct GNUNET_CONTAINER_SList *l,
+                                enum GNUNET_CONTAINER_SListDisposition disp,
+                                const void *buf, size_t len)
+{
+  struct GNUNET_CONTAINER_SList_Elem *e;
+
+  e = create_elem (disp, buf, len);
+  if (l->tail != NULL)
+    l->tail->next = e;
+  if (l->head == NULL)
+    l->head = e;
+  l->tail = e;
   l->length++;
 }
 
 
   l->length++;
 }
 
 
+/**
+ * Append a singly linked list to another
+ * @param dst list to append to
+ * @param src source
+ */
+void
+GNUNET_CONTAINER_slist_append (struct GNUNET_CONTAINER_SList *dst,
+                               struct GNUNET_CONTAINER_SList *src)
+{
+  struct GNUNET_CONTAINER_SList_Iterator i;
+
+  for (i = GNUNET_CONTAINER_slist_begin (src);
+       GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
+       GNUNET_CONTAINER_slist_next (&i))
+
+  {
+    GNUNET_CONTAINER_slist_add (dst,
+                                (i.elem->disp ==
+                                 GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC) ?
+                                GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC :
+                                GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
+                                i.elem->elem, i.elem->len);
+  }
+  GNUNET_CONTAINER_slist_iter_destroy (&i);
+}
+
+
 /**
  * Create a new singly linked list
  * @return the new list
 /**
  * Create a new singly linked list
  * @return the new list
@@ -152,7 +190,7 @@ GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l,
 struct GNUNET_CONTAINER_SList *
 GNUNET_CONTAINER_slist_create ()
 {
 struct GNUNET_CONTAINER_SList *
 GNUNET_CONTAINER_slist_create ()
 {
-  return GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList));
+  return GNUNET_new (struct GNUNET_CONTAINER_SList);
 }
 
 
 }
 
 
@@ -173,14 +211,14 @@ GNUNET_CONTAINER_slist_destroy (struct GNUNET_CONTAINER_SList *l)
  * @param l list
  * @return iterator pointing to the beginning
  */
  * @param l list
  * @return iterator pointing to the beginning
  */
-struct GNUNET_CONTAINER_SList_Iterator *
+struct GNUNET_CONTAINER_SList_Iterator
 GNUNET_CONTAINER_slist_begin (struct GNUNET_CONTAINER_SList *l)
 {
 GNUNET_CONTAINER_slist_begin (struct GNUNET_CONTAINER_SList *l)
 {
-  struct GNUNET_CONTAINER_SList_Iterator *ret;
+  struct GNUNET_CONTAINER_SList_Iterator ret;
 
 
-  ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Iterator));
-  ret->elem = l->head;
-  ret->list = l;
+  memset (&ret, 0, sizeof (ret));
+  ret.elem = l->head;
+  ret.list = l;
   return ret;
 }
 
   return ret;
 }
 
@@ -197,24 +235,26 @@ GNUNET_CONTAINER_slist_clear (struct GNUNET_CONTAINER_SList *l)
 
   e = l->head;
   while (e != NULL)
 
   e = l->head;
   while (e != NULL)
-    {
-      n = e->next;
-      if (e->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC)
-        GNUNET_free (e->elem);
-      GNUNET_free (e);
-      e = n;
-    }
+  {
+    n = e->next;
+    if (e->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC)
+      GNUNET_free (e->elem);
+    GNUNET_free (e);
+    e = n;
+  }
   l->head = NULL;
   l->head = NULL;
+  l->tail = NULL;
   l->length = 0;
 }
 
 
 /**
  * Check if a list contains a certain element
   l->length = 0;
 }
 
 
 /**
  * Check if a list contains a certain element
- *
  * @param l list
  * @param buf payload buffer to find
  * @param len length of the payload (number of bytes in buf)
  * @param l list
  * @param buf payload buffer to find
  * @param len length of the payload (number of bytes in buf)
+ *
+ * @return GNUNET_YES if found, GNUNET_NO otherwise
  */
 int
 GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l,
  */
 int
 GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l,
@@ -228,6 +268,32 @@ GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l,
   return GNUNET_NO;
 }
 
   return GNUNET_NO;
 }
 
+typedef int (*Comparator)(const void *,  size_t, const void *,  size_t);
+
+/**
+ * Check if a list contains a certain element
+ *
+ * @param l list
+ * @param buf payload buffer to find
+ * @param len length of the payload (number of bytes in buf)
+ * @param compare comparison function, should return 0 if compared elements match
+ *
+ * @return NULL if the 'buf' could not be found, pointer to the
+ *         list element, if found
+ */
+void *
+GNUNET_CONTAINER_slist_contains2 (const struct GNUNET_CONTAINER_SList *l,
+                                  const void *buf, size_t len,
+                                  Comparator compare)
+{
+  struct GNUNET_CONTAINER_SList_Elem *e;
+
+  for (e = l->head; e != NULL; e = e->next)
+    if ((e->len == len) && (*compare)(buf, len, e->elem, e->len) == 0)
+      return e->elem;
+  return NULL;
+}
+
 
 /**
  * Count the elements of a list
 
 /**
  * Count the elements of a list
@@ -256,6 +322,8 @@ GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i)
     i->last->next = next;
   else
     i->list->head = next;
     i->last->next = next;
   else
     i->list->head = next;
+  if (next == NULL)
+    i->list->tail = i->last;
   if (i->elem->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC)
     GNUNET_free (i->elem->elem);
   GNUNET_free (i->elem);
   if (i->elem->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC)
     GNUNET_free (i->elem->elem);
   GNUNET_free (i->elem);
@@ -284,6 +352,8 @@ GNUNET_CONTAINER_slist_insert (struct GNUNET_CONTAINER_SList_Iterator *before,
     before->last->next = e;
   else
     before->list->head = e;
     before->last->next = e;
   else
     before->list->head = e;
+  if (e->next == NULL)
+    before->list->tail = e;
   before->list->length++;
 }
 
   before->list->length++;
 }
 
@@ -323,7 +393,7 @@ GNUNET_CONTAINER_slist_end (struct GNUNET_CONTAINER_SList_Iterator *i)
  * @param len payload length
  * @return payload
  */
  * @param len payload length
  * @return payload
  */
-const void *
+void *
 GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i,
                             size_t * len)
 {
 GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i,
                             size_t * len)
 {
@@ -336,9 +406,9 @@ GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i,
  * Release an iterator
  * @param i iterator
  */
  * Release an iterator
  * @param i iterator
  */
-void GNUNET_CONTAINER_slist_iter_destroy (struct GNUNET_CONTAINER_SList_Iterator *i)
+void
+GNUNET_CONTAINER_slist_iter_destroy (struct GNUNET_CONTAINER_SList_Iterator *i)
 {
 {
-  GNUNET_free (i);
 }
 
 /* end of container_slist.c */
 }
 
 /* end of container_slist.c */