/*
- * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <config.h>
#include "list.h"
-#include <assert.h>
/* Initializes 'list' as an empty list. */
void
void
list_splice(struct list *before, struct list *first, struct list *last)
{
- if (first == last)
+ if (first == last) {
return;
+ }
last = last->prev;
/* Cleanly remove 'first'...'last' from its current list. */
}
/* Adjusts pointers around 'list' to compensate for 'list' having been moved
- * around in memory (e.g. as a consequence of realloc()).
+ * around in memory (e.g. as a consequence of realloc()), with original
+ * location 'orig'.
*
- * This always works if 'list' is a member of a list, or if 'list' is the head
- * of a non-empty list. It fails badly, however, if 'list' is the head of an
- * empty list; just use list_init() in that case. */
+ * ('orig' likely points to freed memory, but this function does not
+ * dereference 'orig', it only compares it to 'list'. In a very pedantic
+ * language lawyer sense, this still yields undefined behavior, but it works
+ * with actual compilers.) */
void
-list_moved(struct list *list)
+list_moved(struct list *list, const struct list *orig)
{
- list->prev->next = list->next->prev = list;
+ if (list->next == orig) {
+ list_init(list);
+ } else {
+ list->prev->next = list->next->prev = list;
+ }
+}
+
+/* Initializes 'dst' with the contents of 'src', compensating for moving it
+ * around in memory. The effect is that, if 'src' was the head of a list, now
+ * 'dst' is the head of a list containing the same elements. */
+void
+list_move(struct list *dst, struct list *src)
+{
+ *dst = *src;
+ list_moved(dst, src);
}
/* Removes 'elem' from its list and returns the element that followed it.
struct list *
list_front(const struct list *list_)
{
- struct list *list = (struct list *) list_;
+ struct list *list = CONST_CAST(struct list *, list_);
- assert(!list_is_empty(list));
+ ovs_assert(!list_is_empty(list));
return list->next;
}
struct list *
list_back(const struct list *list_)
{
- struct list *list = (struct list *) list_;
+ struct list *list = CONST_CAST(struct list *, list_);
- assert(!list_is_empty(list));
+ ovs_assert(!list_is_empty(list));
return list->prev;
}
const struct list *e;
size_t cnt = 0;
- for (e = list->next; e != list; e = e->next)
+ for (e = list->next; e != list; e = e->next) {
cnt++;
+ }
return cnt;
}