This commit adds function that allows the appending of one list
content to the other.  Also, it adds functions which allows list
to be sorted.

Signed-off-by: Alex Wang <al...@nicira.com>
---
 lib/list.h        |   67 +++++++++++++++++++++++++++++++++
 tests/library.at  |    2 +-
 tests/test-list.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 174 insertions(+), 1 deletion(-)

diff --git a/lib/list.h b/lib/list.h
index b40bbef..76f930c 100644
--- a/lib/list.h
+++ b/lib/list.h
@@ -30,10 +30,12 @@ static inline void list_poison(struct ovs_list *);
 static inline void list_insert(struct ovs_list *, struct ovs_list *);
 static inline void list_splice(struct ovs_list *before, struct ovs_list *first,
                                struct ovs_list *last);
+static inline void list_join(struct ovs_list *dst, struct ovs_list *src);
 static inline void list_push_front(struct ovs_list *, struct ovs_list *);
 static inline void list_push_back(struct ovs_list *, struct ovs_list *);
 static inline void list_replace(struct ovs_list *, const struct ovs_list *);
 static inline void list_moved(struct ovs_list *, const struct ovs_list *orig);
+static inline void list_swap(struct ovs_list *, struct ovs_list *);
 static inline void list_move(struct ovs_list *dst, struct ovs_list *src);
 
 /* List removal. */
@@ -44,6 +46,8 @@ static inline struct ovs_list *list_pop_back(struct ovs_list 
*);
 /* List elements. */
 static inline struct ovs_list *list_front(const struct ovs_list *);
 static inline struct ovs_list *list_back(const struct ovs_list *);
+static inline struct ovs_list *list_at_position(const struct ovs_list *,
+                                                size_t n);
 
 /* List properties. */
 static inline size_t list_size(const struct ovs_list *);
@@ -101,6 +105,18 @@ list_insert(struct ovs_list *before, struct ovs_list *elem)
     before->prev = elem;
 }
 
+/* Appends 'src''s content to the end of 'dst'.  After 'list_join', 'src'
+ * becomes an empty list. */
+static inline void
+list_join(struct ovs_list *dst, struct ovs_list *src)
+{
+    if (list_is_empty(src)) {
+        return;
+    }
+
+    list_splice(dst, list_front(src), src);
+}
+
 /* Removes elements 'first' though 'last' (exclusive) from their current list,
    then inserts them just before 'before'. */
 static inline void
@@ -149,6 +165,38 @@ list_replace(struct ovs_list *element, const struct 
ovs_list *position)
     element->prev->next = element;
 }
 
+/* Swaps the two adjacent list elements. 'ahead' must be ahead of 'after'. */
+static inline void
+list_swap_adjacent(struct ovs_list *ahead, struct ovs_list *after)
+{
+    ahead->next = after->next;
+    ahead->next->prev = ahead;
+    after->prev = ahead->prev;
+    ahead->prev->next = after;
+    ahead->prev = after;
+    after->next = ahead;
+}
+
+/* Swaps the position of two list nodes, 'elem1' and 'elem2'. */
+static inline void
+list_swap(struct ovs_list *elem1, struct ovs_list *elem2)
+{
+    if (elem1 == elem2) {
+        return;
+    } else if (elem1->prev == elem2) {
+        /* element2 is ahead of element1. */
+        list_swap_adjacent(elem2, elem1);
+    } else if (elem2->prev == elem1) {
+        /* element1 is ahead of element2. */
+        list_swap_adjacent(elem1, elem2);
+    } else {
+        const struct ovs_list tmp = *elem1;
+
+        list_replace(elem1, elem2);
+        list_replace(elem2, &tmp);
+    }
+}
+
 /* Adjusts pointers around 'list' to compensate for 'list' having been moved
  * around in memory (e.g. as a consequence of realloc()), with original
  * location 'orig'.
@@ -233,6 +281,25 @@ list_back(const struct ovs_list *list_)
     return list->prev;
 }
 
+/* Returns the element at position 'n', assumes the first element is
+ * at index 0.  The 'list_' must contain at least 'n' elements. */
+static inline struct ovs_list *
+list_at_position(const struct ovs_list *list_, size_t n)
+{
+    struct ovs_list *list = CONST_CAST(struct ovs_list *, list_);
+    struct ovs_list *ret;
+    size_t cnt = 0;
+
+    for (ret = list->next; ret != list; ret = ret->next) {
+        if (cnt++ == n) {
+            return ret;
+        }
+    }
+    ovs_assert(false);
+
+    return NULL;
+}
+
 /* Returns the number of elements in 'list'.
    Runs in O(n) in the number of elements. */
 static inline size_t
diff --git a/tests/library.at b/tests/library.at
index 2507688..fab7402 100644
--- a/tests/library.at
+++ b/tests/library.at
@@ -38,7 +38,7 @@ AT_CHECK([ovstest test-atomic])
 AT_CLEANUP
 
 AT_SETUP([test linked lists])
-AT_CHECK([ovstest test-list], [0], [..
+AT_CHECK([ovstest test-list], [0], [......
 ])
 AT_CLEANUP
 
diff --git a/tests/test-list.c b/tests/test-list.c
index 5fd7149..3652064 100644
--- a/tests/test-list.c
+++ b/tests/test-list.c
@@ -20,6 +20,7 @@
 #include <config.h>
 #undef NDEBUG
 #include "list.h"
+#include "sort.h"
 #include <assert.h>
 #include <string.h>
 #include "ovstest.h"
@@ -160,6 +161,107 @@ test_list_for_each_safe(void)
 }
 
 static void
+test_list_swap_elem(void)
+{
+    enum { MAX_ELEMS = 100 };
+    struct element elements[MAX_ELEMS];
+    int values[MAX_ELEMS];
+    size_t n = MAX_ELEMS;
+    struct ovs_list list;
+
+    make_list(&list, elements, values, n);
+    elements[1].value = 50;
+    elements[50].value = 1;
+    list_swap(&elements[1].node, &elements[50].node);
+    elements[9].value = 10;
+    elements[10].value = 9;
+    list_swap(&elements[9].node, &elements[10].node);
+    elements[19].value = 20;
+    elements[20].value = 19;
+    list_swap(&elements[20].node, &elements[19].node);
+    list_swap(&elements[29].node, &elements[29].node);
+    check_list(&list, values, n);
+}
+
+static void
+test_list_at_position(void)
+{
+    enum { MAX_ELEMS = 10 };
+    struct element elements[MAX_ELEMS];
+    int values[MAX_ELEMS];
+    size_t n = MAX_ELEMS;
+    struct ovs_list list;
+
+    make_list(&list, elements, values, n);
+    for (n = 0; n < MAX_ELEMS; n++) {
+        struct ovs_list *node = list_at_position(&list, n);
+
+        ovs_assert(node == &elements[n].node);
+    }
+}
+
+static int
+test_list_compare(size_t a, size_t b, void *aux)
+{
+    struct ovs_list *list = aux;
+    struct element *elem1, *elem2;
+
+    elem1 = CONTAINER_OF(list_at_position(list, a), struct element, node);
+    elem2 = CONTAINER_OF(list_at_position(list, b), struct element, node);
+
+    return elem1->value - elem2->value;
+}
+
+static void
+test_list_swap(size_t a, size_t b, void *aux)
+{
+    struct ovs_list *list = aux;
+
+    list_swap(list_at_position(list, a), list_at_position(list, b));
+}
+
+static void
+test_list_sort(void)
+{
+    enum { MAX_ELEMS = 10 };
+    struct element elements[MAX_ELEMS];
+    int values[MAX_ELEMS];
+    size_t n = MAX_ELEMS;
+    struct ovs_list list;
+
+    make_list(&list, elements, values, n);
+    for (n = 0; n < MAX_ELEMS; n++) {
+        elements[n].value = MAX_ELEMS - 1 - n;
+    }
+    /* Sorts the list in ascending order of priority. */
+    sort(n, test_list_compare, test_list_swap, &list);
+    check_list(&list, values, n);
+}
+
+static void
+test_list_join(void)
+{
+    enum { MAX_ELEMS = 10 };
+    struct element elements_1[MAX_ELEMS];
+    struct element elements_2[MAX_ELEMS];
+    int values[2*MAX_ELEMS];
+    size_t n = MAX_ELEMS;
+    struct ovs_list list_dst, list_src;
+
+    make_list(&list_dst, elements_1, values, n);
+    make_list(&list_src, elements_2, values, n);
+    /* Makes 'elements_2' contains values {MAX_ELEMS..2*MAX_ELEMS-1}. */
+    for (n = MAX_ELEMS; n < 2*MAX_ELEMS; n++) {
+        elements_2[n-MAX_ELEMS].value += MAX_ELEMS;
+        values[n] = n;
+    }
+
+    list_join(&list_dst, &list_src);
+    assert(list_is_empty(&list_src));
+    check_list(&list_dst, values, 2*MAX_ELEMS);
+}
+
+static void
 run_test(void (*function)(void))
 {
     function();
@@ -171,6 +273,10 @@ test_list_main(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
 {
     run_test(test_list_construction);
     run_test(test_list_for_each_safe);
+    run_test(test_list_swap_elem);
+    run_test(test_list_at_position);
+    run_test(test_list_sort);
+    run_test(test_list_join);
     printf("\n");
 }
 
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to