RList
|
#include <stddef.h>
#include <stdbool.h>
#include <assert.h>
#include "rlist/platform.h"
#include "rlist/common.h"
Go to the source code of this file.
Data Structures | |
struct | drl_list |
struct | drl_iterator |
Defines | |
#define | DRL_INIT { 0, NULL, NULL, NULL } |
#define | DRL_INIT_WITH(free_fn) { 0, free_fn, NULL, NULL } |
Typedefs | |
typedef int(* | drl_map_fn )(struct drl_iterator *const iter, void *const context) |
Functions | |
static void * | drl_payload (const struct drl_iterator *const iter) |
static void | drl_init (struct drl_list *const list, rl_free_fn free_fn) |
static unsigned int | drl_size (const struct drl_list *const list) |
static struct drl_iterator * | drl_first (struct drl_list *const list, struct drl_iterator *const iter) |
static struct drl_iterator * | drl_last (struct drl_list *const list, struct drl_iterator *const iter) |
static struct drl_iterator * | drl_next (struct drl_iterator *const iter) |
static struct drl_iterator * | drl_prev (struct drl_iterator *const iter) |
static bool | drl_is_eol (const struct drl_iterator *const iter) |
bool | drl_insert_before (struct drl_iterator *const iter, void *const payload) |
void * | drl_del (struct drl_iterator *const iter) |
void | drl_del_all (struct drl_list *const list) |
struct drl_iterator * | drl_find (struct drl_iterator *const iter, rl_match_fn match_fn, void *const match_context) |
struct drl_iterator * | drl_find_payload (struct drl_iterator *const iter, void *const payload) |
int | drl_map (struct drl_iterator *const iter, drl_map_fn map_fn, void *const map_context, rl_match_fn match_fn, void *const match_context) |
Public RList API for doubly linked lists.
Definition in file double.h.
#define DRL_INIT { 0, NULL, NULL, NULL } |
An initializer constant for drl_list objects.
After assigning this value to a list, it is empty and not associated with an rl_free_fn() function.
Static or local declarations of drl_list objects should be initialized in the declaration with this value (e.g., static struct drl_list list = DRL_INIT;
). The drl_init() function should be used where initialization at compile time is not possible so it has to occur at runtime, e.g., for dynamically allocated drl_list objects.
#define DRL_INIT_WITH | ( | free_fn | ) | { 0, free_fn, NULL, NULL } |
An initializer constant for drl_list objects with a custom call-back function for de-allocating payload data.
After assigning this value to a list, it is empty and has the specified rl_free_fn() function associated.
Static or local declarations of drl_list objects should be initialized in the declaration with this value (e.g., static struct drl_list list = DRL_INIT;
). The drl_init() function should be used where initialization at compile time is not possible so it has to occur at runtime, e.g., for dynamically allocated drl_list objects.
free_fn | points to a function with the type rl_free_fn() for de-allocating payload data. |
typedef int(* drl_map_fn)(struct drl_iterator *const iter, void *const context) |
A type for call-back functions that are applied to multiple list nodes.
Typically, call-backs of this type are used to apply a certain operation (such as modifying the payload or deleting nodes) to some or all nodes in a list (
Using call-back functions for these operations gives the user of drl_list full customizability on the action performed on the list nodes while the generic iteration code is provided as an RList function and does not need to be re-implemented and customized over and over.
iter | points to an iterator that refers to a list node. The call-back function may freely manipulate the node's payload. It may also freely manipulate the iterator via any of the RList functions, including deleting the current node. |
context | points to a custom memory location that the call-back function requires as input or for storing data across calls. |
void* drl_del | ( | struct drl_iterator *const | iter | ) |
Delete a node from a list.
This function deletes the node that the given iterator refers to.
The runtime complexity of this function is O(1).
iter | Points to an iterator object. The iterator may not be uninitialized and must have previously been returned by one of the RList functions. The result of calling this function with iter == NULL is undefined. |
NULL
. Note that if in this case the payload is present more than once in the list, it is indeed de-allocated but other list nodes with the same payload remain in the list and still point to the now de-allocated payload memory. Thus, inserting a payload more than once into a list should be avoided. If the list is not associated with an rl_free_fn() call-back function, the payload is not de-allocated and this function returns the payload of the deleted node. Note that the payload itself may be NULL
. void drl_del_all | ( | struct drl_list *const | list | ) |
Delete all nodes from a list.
This is a convenience function which calls drl_del() for all nodes of a list.
The runtime complexity of this function is O(n).
list | Points to the list object from which to delete all nodes. The result of calling this function with list == NULL is undefined. |
struct drl_iterator* drl_find | ( | struct drl_iterator *const | iter, |
rl_match_fn | match_fn, | ||
void *const | match_context | ||
) | [read] |
Find a list node based on a match call-back function.
This function iterates linearly over a list, starting at the given iterator position, and applies the given matcher call-back function to each list node. It returns an iterator for the first matching node.
The average runtime complexity of this function is O(n/2) + O(match_fn) when iter refers to the first list node.
iter | Points to an iterator object. The iterator indicates the list to search and the list node to begin the search at. The result of calling this function with iter == NULL or an uninitialized iterator object is undefined. |
match_fn | Points to a call-back function that identifies the list node to return. The result of calling this function with match_fn == NULL is undefined. |
match_context | A context object passed to match_fn on every invocation as its second parameter. The semantics of match_context depend solely on the implementation of the match_fn call-back. match_context may be NULL if match_fn supports that. |
struct drl_iterator* drl_find_payload | ( | struct drl_iterator *const | iter, |
void *const | payload | ||
) | [read] |
Find a list node with a certain payload.
This is a convenience function implemented via drl_find().
The average runtime complexity of this function is O(n/2) when iter refers to the first list node.
iter | Points to an iterator object. The iterator indicates the list to search and the list node to begin the search at. The result of calling this function with iter == NULL or an uninitialized iterator object is undefined. |
payload | points to the payload to find in list. If payload is NULL , the first list node with a NULL payload is searched for. |
static struct drl_iterator* drl_first | ( | struct drl_list *const | list, |
struct drl_iterator *const | iter | ||
) | [static, read] |
Initialize an iterator object so it refers to the first node in a list.
If the list is empty, the iterator is updated so that drl_is_eol() returns true.
The runtime complexity of this function is O(1).
list | Points to the list from which to retrieve the first node. The result of calling this function with list == NULL is undefined. |
iter | Points to the iterator object to initialize. The result of calling this function with iter == NULL is undefined. |
static void drl_init | ( | struct drl_list *const | list, |
rl_free_fn | free_fn | ||
) | [inline, static] |
Initialize a drl_list object at runtime.
This function should be used where initialization at compile time is not possible so it has to occur at runtime, e.g., for dynamically allocated drl_list objects. Static or local declarations of drl_list objects should be initialized in their declaration via DRL_INIT.
The runtime complexity of this function is O(1).
list | points to the list object to initialize. The result of calling this function with list == NULL is undefined. |
free_fn | points to a rl_free_fn() call-back function for de-allocating payload data. If free_fn is NULL , the list does not automatically de-allocate payload data. Proper memory management of the payload data is then the responsibility of the user of list. |
bool drl_insert_before | ( | struct drl_iterator *const | iter, |
void *const | payload | ||
) |
Add payload as a new node at a specific location of a list.
The runtime complexity of this function is O(1).
iter | Points to an iterator. The new node is inserted between the iterator's node and its predecessor. If iter refers to the end of the list (i.e., when drl_is_eol(iter) returns true ), the new node is inserted as the last node in the list. This also works for inserting the first node into an empty list. The result of calling this function with iter == NULL is undefined. |
payload | Points to the payload to add to the list. payload may be NULL , in which case a node with a NULL payload is prepended to the list. The same payload may be added to a list several times. In that case however, one needs to be particularly careful about when to de-allocate the payload data. Otherwise, one list node may still point to payload that has already been de-allocated for another list node. |
static bool drl_is_eol | ( | const struct drl_iterator *const | iter | ) | [inline, static] |
Determine whether an iterator refers to either end of a list, i.e., whether it iterated beyond the last list node or before the first list node.
This is primarily useful to determine when an iteration over a list has ended. In this state, the iterator does not refer to a valid list node and should not be passed to any RList functions except drl_is_eol().
The runtime complexity of this function is O(1).
iter | Points to the iterator object to check. The result of calling this function with iter == NULL is undefined. |
static struct drl_iterator* drl_last | ( | struct drl_list *const | list, |
struct drl_iterator *const | iter | ||
) | [static, read] |
Initialize an iterator object so it refers to the last node in a list.
If the list is empty, the iterator is updated so that drl_is_eol() returns true.
The runtime complexity of this function is O(1).
list | Points to the list from which to retrieve the last node. The result of calling this function with list == NULL is undefined. |
iter | Points to the iterator object to initialize. The result of calling this function with iter == NULL is undefined. |
int drl_map | ( | struct drl_iterator *const | iter, |
drl_map_fn | map_fn, | ||
void *const | map_context, | ||
rl_match_fn | match_fn, | ||
void *const | match_context | ||
) |
Applies a call-back function to some or all nodes of a list.
This function linearly iterates over a list, starting at the given iterator. For each node, it first checks if an optional rl_match_fn() call-back matches the node. If the node is a match or no rl_match_fn() call-back is supplied, this function invokes the drl_map_fn() call-back for the node. It continues until the end of the list is reached or until the drl_map_fn() call-back returns a non-zero integer.
The average runtime complexity of this function is O(n/2) + O(match_fn) + O(map_fn) when iter refers to the first list node.
iter | Points to an iterator object. The iterator indicates the list to map map_fn onto and it specifies the list node to begin the map operation at. The result of calling this function with iter == NULL or an uninitialized iterator object is undefined. |
map_fn | points to the call-back function to invoke on every node matching match_fn. The result of calling this function with map_fn == NULL is undefined. |
map_context | A context object passed to map_fn on every invocation as its second parameter. The semantics of map_context depend solely on the implementation of the map_fn call-back. map_context may be NULL if map_fn supports that. |
match_fn | points to the call-back function that identifies the subset of nodes that map_fn is invoked for. If match_fn is NULL , map_fn is invoked for all list nodes. |
match_context | A context object passed to match_fn on every invocation as its second parameter. The semantics of match_context depend solely on the implementation of the match_fn call-back. match_context may be NULL if match_fn supports that. |
static struct drl_iterator* drl_next | ( | struct drl_iterator *const | iter | ) | [static, read] |
Update an iterator object so it refers to the 'next' list node, i.e., the node following the one the iterator refers to before calling this function.
After passing an iterator to drl_del(), you must call drl_next() or drl_prev() on the same iterator before passing it to any other RList function. This advances the iterator to the node after or before the deleted node.
This function is primarily intended for iterating through a list.
The runtime complexity of this function is O(1).
iter | Points to an iterator object. The iterator may not be uninitialized and must have previously been returned by one of the RList functions. If iter refers to either end of the list, i.e., if drl_is_eol(iter) returns true, this function does not modify iter. The result of calling this function with iter == NULL is undefined. |
static void* drl_payload | ( | const struct drl_iterator *const | iter | ) | [inline, static] |
Retrieve the payload an iterator object is associated with.
The runtime complexity of this function is O(1).
iter | points to the iterator for which to retrieve the payload pointer. The result of calling this function with iter == NULL is undefined. The result of calling this function with an inconsistent iterator ( |
static struct drl_iterator* drl_prev | ( | struct drl_iterator *const | iter | ) | [static, read] |
Update an iterator object so it refers to the 'previous' list node, i.e., the node preceeding the one the iterator refers to before calling this function.
After passing an iterator to drl_del(), you must call drl_next() or drl_prev() on the same iterator before passing it to any other RList function. This advances the iterator to the node after or before the deleted node.
This function is primarily intended for iterating through a list.
The runtime complexity of this function is O(1).
iter | Points to an iterator object. The iterator may not be uninitialized and must have previously been returned by one of the RList functions. If iter refers to either end of the list, i.e., if drl_is_eol(iter) returns true, this function does not modify iter. The result of calling this function with iter == NULL is undefined. |
static unsigned int drl_size | ( | const struct drl_list *const | list | ) | [inline, static] |
Retrieve the number of nodes currently held by a list.
The runtime complexity of this function is O(1).
list | points to the list object of which to retrieve the node count. The result of calling this function with list == NULL is undefined. |