Defines a simple double link structure and inline functions to manipulate them. This is intended as a low-level functionality used to define higher level structures.
These links are represented as cyclic. When used as a list, the cycle is broken by one special head link which is used to refer to the whole list, and which may represent the past-the-end iterator.
size_t cu_dlink_card | ( | cu_dlink_t | l | ) |
Return the number of element of the cycle of which l is a member. This takes linear time in the number of nodes.
cu_bool_t cu_dlink_card_eq_2 | ( | cu_dlink_t | l | ) |
True iff the cardinality of l is 2.
cu_bool_t cu_dlink_card_leq_1 | ( | cu_dlink_t | l | ) |
True iff the cardinality of l is at most 1.
cu_bool_t cu_dlink_card_leq_2 | ( | cu_dlink_t | l | ) |
True iff the cardinality of l is at most 2.
size_t cu_dlink_card_lim | ( | cu_dlink_t | l, | |
size_t | limit | |||
) |
Return minimum of the limit and the number of elements of l. The limit allows quick return if the client is only needs to distinguish cases up to a certain number. Pass SIZE_MAX
for limit for a full count.
cu_dlink_t cu_dlink_cat_d | ( | cu_dlink_t | l0, | |
cu_dlink_t | l1 | |||
) |
Concatenate l0 and l1 and return the result. This uses cu_dlink_splice_before if applicable, and in case l0 is not NULL
, it will form the first part of the cycle as seen from the returned link. The arguments shall be considered destructed, as indicated by the _d
suffix.
cu_bool_t cu_dlink_cocyclic | ( | cu_dlink_t | l0, | |
cu_dlink_t | l1 | |||
) |
True iff l0 and l1 are part of the same cycle. Runs in linear time in the smaller of the cardinalities of the two arguments.
NULL
. void cu_dlink_erase | ( | cu_dlink_t | l | ) |
Erases and invalidates l from the link it is part of. l must not be singular.
void cu_dlink_extract | ( | cu_dlink_t | l | ) |
Removes l from its cycle and reconstruct it as an singleton.
void cu_dlink_init_singleton | ( | cu_dlink_t | l_init | ) |
Initialise l_init as a link with next and prev pointing to itself. This is typically used as the head of doubly linked lists.
void cu_dlink_insert_after | ( | cu_dlink_t | l, | |
cu_dlink_t | l_init | |||
) |
Initialise l_init as the successor of l.
NULL
. void cu_dlink_insert_before | ( | cu_dlink_t | l, | |
cu_dlink_t | l_init | |||
) |
Initialise l_init as the predecessor of l.
NULL
. cu_bool_t cu_dlink_is_singleton | ( | cu_dlink_t | l | ) |
True iff l is a singleton.
void cu_dlink_move_after | ( | cu_dlink_t | l, | |
cu_dlink_t | l_mv | |||
) |
Move l_mv right after l. This works whether they are in the same or in different cycles.
NULL
and l != l_mv. void cu_dlink_move_before | ( | cu_dlink_t | l, | |
cu_dlink_t | l_mv | |||
) |
Move l_mv right before l. This works whether they are in the same or in different cycles.
NULL
and l != l_mv. void cu_dlink_splice_after | ( | cu_dlink_t | l0, | |
cu_dlink_t | l1 | |||
) |
Splice l0 and l1 right after the given nodes, otherwise the same as cu_dlink_splice_before.
void cu_dlink_splice_before | ( | cu_dlink_t | l0, | |
cu_dlink_t | l1 | |||
) |
Splice l0 and l1 right before the given nodes. If l0 and l1 are links of the same cycle, then the cycle is split into two cycles, otherwise the two separate cycles forms a single cycle. This operation can therefore be used as concatenation if sentinel nodes are not used.
NULL
. void cu_dlink_splice_complement_after | ( | cu_dlink_t | l, | |
cu_dlink_t | l_excl | |||
) |
Erase l_excl from its cycle and splice the remaining cycle right after l, otherwise works like cu_dlink_splice_complement_before.
void cu_dlink_splice_complement_before | ( | cu_dlink_t | l, | |
cu_dlink_t | l_excl | |||
) |
Drop l_excl from its cycle and splice the remaining cycle (the complement) right before l. If the two arguments are the EOL sentinel nodes of lists, this concatenates them.
NULL
. void cu_dlink_validate | ( | cu_dlink_t | l | ) |
Validate the link integrity of l.