On Mon, Jun 1, 2015 at 11:24 AM, Alex Wang <al...@nicira.com> wrote:
> 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>
> ---
> RFC->RFC V2:
> - Adopt Ben's suggestions.
>
> ---
>  lib/list.h        |   48 ++++++++++++++++++++++++
>  tests/library.at  |    2 +-
>  tests/test-list.c |  106 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 155 insertions(+), 1 deletion(-)
>
> diff --git a/lib/list.h b/lib/list.h
> index 7ba1e35..229f1c3 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 *);
> @@ -104,6 +108,14 @@ 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)
> +{
> +    list_splice(dst, src->next, src);
> +}
> +
>  /* Removes elements 'first' though 'last' (exclusive) from their current 
> list,
>     then inserts them just before 'before'. */
>  static inline void
> @@ -152,6 +164,25 @@ list_replace(struct ovs_list *element, const struct 
> ovs_list *position)
>      element->prev->next = element;
>  }
>
> +/* Exchanges the positions of A and B, which may be in the same list
> + * or different lists. */
May need to check for list_empty() for a and b, or make it clear in
the comment that they
are not expected.
> +static inline void
> +list_swap(struct ovs_list *a, struct ovs_list *b)
> +{
> +    if (a != b) {
> +        if (a->next != b) {
> +            struct ovs_list *a_next = list_remove(a);
> +            struct ovs_list *b_next = list_remove(b);
> +
> +            list_insert(b_next, a);
> +            list_insert(a_next, b);
> +        } else {
> +            list_remove(b);
> +            list_insert(a, b);
> +        }
> +    }
> +}
> +
>  /* 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'.
> @@ -236,6 +267,23 @@ 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) {
How about change to if (!n--)?  We don't need to maintain the 'cnt' variable.
> +            return ret;
> +        }
> +    }
> +    OVS_NOT_REACHED();
> +}
> +
>  /* 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 9bd6d81..cb1f858 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 9b6b0bd..5c16990 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"
> @@ -185,6 +186,107 @@ test_list_for_each_pop(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();
> @@ -197,6 +299,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_for_each_pop);
> +    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
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to