Add new functions to the list_head system.
This commit is contained in:
+48
-14
@@ -22,31 +22,37 @@ typedef struct list_head {
|
||||
#define list_entry(ptr, type, member) container_of(ptr, type, member)
|
||||
|
||||
/// @brief Iterates over a list.
|
||||
/// @param pos The &list_head to use as a loop cursor.
|
||||
/// @param head The head for your list.
|
||||
/// @param pos the name of the iterator used to visit the list.
|
||||
/// @param head the head for your list.
|
||||
#define list_for_each(pos, head) \
|
||||
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
|
||||
|
||||
/// @brief Iterates over a list backwards.
|
||||
/// @param pos The &list_head to use as a loop cursor.
|
||||
/// @param head The head for your list.
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for ((pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev)
|
||||
|
||||
/// @brief Iterates over a list safe against removal of list entry.
|
||||
/// @param pos The &list_head to use as a loop cursor.
|
||||
/// @param store Another &list_head to use as temporary storage.
|
||||
/// @param head The head for your list.
|
||||
/// @param pos the name of the iterator used to visit the list.
|
||||
/// @param store another list iterator to use as temporary storage.
|
||||
/// @param head the head for your list.
|
||||
#define list_for_each_safe(pos, store, head) \
|
||||
for ((pos) = (head)->next, (store) = (pos)->next; (pos) != (head); \
|
||||
(pos) = (store), (store) = (pos)->next)
|
||||
|
||||
/// @brief Iterates over a list.
|
||||
/// @param pos The &list_head to use as a loop cursor.
|
||||
/// @param head The head for your list.
|
||||
/// @brief Iterates over a list, but declares the iterator.
|
||||
/// @param pos the name of the iterator used to visit the list.
|
||||
/// @param head the head for your list.
|
||||
#define list_for_each_decl(pos, head) \
|
||||
for (list_head * (pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
|
||||
|
||||
/// @brief Iterates over a list backwards.
|
||||
/// @param pos the name of the iterator used to visit the list.
|
||||
/// @param head the head for your list.
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for ((pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev)
|
||||
|
||||
/// @brief Iterates over a list backwards, but declares the iterator.
|
||||
/// @param pos the name of the iterator used to visit the list.
|
||||
/// @param head the head for your list.
|
||||
#define list_for_each_prev_decl(pos, head) \
|
||||
for (list_head * (pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev)
|
||||
|
||||
/// @brief Initializes the list_head.
|
||||
/// @param head The head of your list.
|
||||
static inline void list_head_init(list_head *head)
|
||||
@@ -161,3 +167,31 @@ static inline void list_head_append(list_head *main, list_head *secondary)
|
||||
list_head_init(secondary);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Replaces entry1 with entry2, entry1 will be removed from the list.
|
||||
/// @param entry1 the first entry to remove.
|
||||
/// @param entry2 the second entry which will take the place of the first entry.
|
||||
static inline void list_head_replace(list_head *entry1, list_head *entry2)
|
||||
{
|
||||
// First we need to remove the second entry.
|
||||
list_head_remove(entry2);
|
||||
// Then, we can place second entry where the first entry is.
|
||||
entry2->next = entry1->next;
|
||||
entry2->next->prev = entry2;
|
||||
entry2->prev = entry1->prev;
|
||||
entry2->prev->next = entry2;
|
||||
// Re-initialize the first entry.
|
||||
list_head_init(entry1);
|
||||
}
|
||||
|
||||
/// @brief Swaps entry1 and entry2 inside the list.
|
||||
/// @param entry1 the first entry.
|
||||
/// @param entry2 the second entry.
|
||||
static inline void list_head_swap(list_head *entry1, list_head *entry2)
|
||||
{
|
||||
list_head *pos = entry2->prev;
|
||||
list_head_replace(entry1, entry2);
|
||||
if (pos == entry1)
|
||||
pos = entry2;
|
||||
list_head_insert_after(entry1, pos);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/// @file list_head_algorithm.h
|
||||
/// @author Enrico Fraccaroli (enry.frak@gmail.com)
|
||||
/// @brief Some general algorithm that might come in handy while using list_head.
|
||||
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "list_head.h"
|
||||
|
||||
/// @brief list_head comparison function.
|
||||
typedef int (*list_head_compare)(const list_head *, const list_head *);
|
||||
|
||||
/// @brief -
|
||||
/// @param list
|
||||
/// @param compare
|
||||
void list_head_sort(list_head *list, list_head_compare compare)
|
||||
{
|
||||
list_head *current = NULL, *index = NULL, *next = NULL;
|
||||
// Check whether list is empty
|
||||
if (list_head_empty(list)) {
|
||||
return;
|
||||
}
|
||||
// Keeps track if we need to restart the outer loop.
|
||||
int restart = 0;
|
||||
// Current will point to head
|
||||
for (current = list->next; current->next != list;) {
|
||||
// Save pointer to next.
|
||||
next = current->next;
|
||||
// Reset restart flag.
|
||||
restart = 0;
|
||||
// Index will point to node next to current
|
||||
for (index = current->next; index != list; index = index->next) {
|
||||
// If current's data is greater than index's data, swap the data of
|
||||
// current and index
|
||||
if (compare(current, index)) {
|
||||
list_head_swap(index, current);
|
||||
restart = 1;
|
||||
}
|
||||
}
|
||||
// Check if we need to restart.
|
||||
if (restart)
|
||||
current = list->next;
|
||||
else
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user