libamxc  1.10.3
C Generic Data Containers
Linked List

The Ambiorix Linked List is a doubly linked list. More...

Collaboration diagram for Linked List:

Modules

 Linked List Iterator
 

Data Structures

struct  _amxc_llist
 The linked list structure. More...
 

Macros

#define amxc_llist_for_each(it, list)
 Loops over the list from head to tail. More...
 
#define amxc_llist_iterate(it, list)
 Loops over the list from head to tail. More...
 
#define amxc_llist_for_each_reverse(it, list)
 Loops over the list from tail to head. More...
 
#define amxc_llist_iterate_reverse(it, list)
 Loops over the list from tail to head. More...
 

Typedefs

typedef struct _amxc_llist amxc_llist_t
 The linked list structure. More...
 
typedef void(* amxc_llist_it_delete_t) (amxc_llist_it_t *it)
 Definition of the linked list item delete function. More...
 

Functions

int amxc_llist_new (amxc_llist_t **llist)
 Allocates a linked list. More...
 
void amxc_llist_delete (amxc_llist_t **llist, amxc_llist_it_delete_t func)
 Frees the previously allocated linked list. More...
 
int amxc_llist_init (amxc_llist_t *const llist)
 Initializes a linked list. More...
 
void amxc_llist_clean (amxc_llist_t *const llist, amxc_llist_it_delete_t func)
 Removes all items from the linked list. More...
 
int amxc_llist_move (amxc_llist_t *const dest, amxc_llist_t *const src)
 Moves all items from one linked list to another linked list. More...
 
bool amxc_llist_is_empty (const amxc_llist_t *const llist)
 Checks that the linked list is empty. More...
 
size_t amxc_llist_size (const amxc_llist_t *const llist)
 Calculates the size of the linked list. More...
 
int amxc_llist_append (amxc_llist_t *const llist, amxc_llist_it_t *const it)
 Adds an item to the end of the linked list. More...
 
int amxc_llist_prepend (amxc_llist_t *const llist, amxc_llist_it_t *const it)
 Adds an item to the beginning of the linked list. More...
 
amxc_llist_it_tamxc_llist_get_at (const amxc_llist_t *const llist, const unsigned int index)
 Gets an item at a certain position of the linked list. More...
 
int amxc_llist_set_at (amxc_llist_t *llist, const unsigned int index, amxc_llist_it_t *const it)
 Inserts an item at a certain position. More...
 
int amxc_llist_sort (amxc_llist_t *const llist, amxc_llist_it_cmp_t cmp)
 Sorts a linked list. More...
 
AMXC_INLINE amxc_llist_it_tamxc_llist_get_first (const amxc_llist_t *const llist)
 Gets the first item of the linked list. More...
 
AMXC_INLINE amxc_llist_it_tamxc_llist_get_last (const amxc_llist_t *const llist)
 Gets the last item of the linked list. More...
 
AMXC_INLINE amxc_llist_it_tamxc_llist_take_first (amxc_llist_t *const llist)
 Removes the first item from the linked list. More...
 
AMXC_INLINE amxc_llist_it_tamxc_llist_take_last (amxc_llist_t *const llist)
 Removes the last item from the linked list. More...
 
AMXC_INLINE amxc_llist_it_tamxc_llist_take_at (const amxc_llist_t *llist, const unsigned int index)
 Removes an item at a certain position of the linked list. More...
 

Detailed Description

The Ambiorix Linked List is a doubly linked list.

A doubly linked list is a linked data structure that consists of a set of sequentially linked records called nodes. Each node contains two fields: a reference to the previous and to the next node in the sequence of nodes. The beginning and ending nodes' previous and next links, respectively, point to some kind of terminator, typically a sentinel node or null, to facilitate traversal of the list.

The linked list itself contains two fields: a reference to the first node and a reference to the last node

The nodes of an Ambiorix linked list are defined using the amxc_llist_it_t structure (the iterator). To create a linked list of a C structure, put an linked list iterator as member of that structure.

typedef struct person {
char* first_name;
char* last_name;
uint32_t age;
} person_t;
The linked list iterator structure.
Definition: amxc_llist.h:215
static amxc_htable_it_t it[2000]
Creating A Linked List
A linked list can be declared on the stack or allocated in the heap. When declaring a linked list on the stack it must be correctly initialized.
Adding items
Items can be added:
Looping Over A Linked List
Looping over a linked list can be done using the defined macros:

You can implement your own loop and use the linked list navigation functions:

Convert An Linked List Iterator To Data Struct
Using the macro amxc_container_of (or amxc_llist_it_get_data) the address of the containing data structure is calculated:
(data address) = (iterator address) - (offsetof(<type>, <member>))
char data[]
Removing An Item
Any item can be removed from the linked list without deleting the item itself.
Deleting An Item
Most of the time items in the linked list are allocated on the heap. The linked list implementation can not by itself delete the allocated memory for the item, but a callback function can be provided to achieve this.

Deleting an item can be done using:

Example
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <amxc/amxc.h>
typedef struct person {
char first_name[64];
char last_name[64];
uint32_t age;
} person_t;
static void delete_person(amxc_llist_it_t* it) {
person_t *person = amxc_container_of(it, person_t, it);
free(person);
}
int main(int argc, char** argv) {
amxc_llist_t contacts;
person_t *person = NULL;
amxc_llist_init(&contacts)
for(uint32_t i = 0; i < 10; i++) {
person = (person_t *)calloc(1, sizeof(person_t));
snprintf(person->first_name, 64, "first_name %d", i);
snprintf(person->last_name, 64, "last_name %d", i);
person->age = i;
amxc_llist_append(&contacts, &person->it);
}
amxc_llist_for_each(it, (&contacts)) {
person = amxc_container_of(it, person_t, it);
printf("%s %s %d\n". person->first_name, person->last_name, person->age);
}
amxc_llist_clean(&contacts, delete_person);
return 0;
}
int main(void)
Definition: test_main.c:62
#define amxc_container_of(addr, type, member)
Calculates the address of the containing structure.
Definition: amxc_common.h:83
int amxc_llist_append(amxc_llist_t *const llist, amxc_llist_it_t *const it)
Adds an item to the end of the linked list.
Definition: amxc_llist.c:169
int amxc_llist_init(amxc_llist_t *const llist)
Initializes a linked list.
Definition: amxc_llist.c:111
void amxc_llist_clean(amxc_llist_t *const llist, amxc_llist_it_delete_t func)
Removes all items from the linked list.
Definition: amxc_llist.c:124
#define amxc_llist_for_each(it, list)
Loops over the list from head to tail.
Definition: amxc_llist.h:253
The linked list structure.
Definition: amxc_llist.h:228

Macro Definition Documentation

◆ amxc_llist_for_each

#define amxc_llist_for_each (   it,
  list 
)
Value:
* it ## _next = amxc_llist_it_get_next(it); \
it; \
it = it ## _next, \
it ## _next = amxc_llist_it_get_next(it))
AMXC_INLINE amxc_llist_it_t * amxc_llist_it_get_next(const amxc_llist_it_t *const reference)
Gets the next iterator in the list.
Definition: amxc_llist.h:824
AMXC_INLINE amxc_llist_it_t * amxc_llist_get_first(const amxc_llist_t *const llist)
Gets the first item of the linked list.
Definition: amxc_llist.h:713

Loops over the list from head to tail.

Iterates over the list and updates the iterator each time.

Warning
Do not modify the list itself while using this macro. It is possible to nest this macro It is allowed to delete or remove the current iterator from the list.

Definition at line 253 of file amxc_llist.h.

◆ amxc_llist_for_each_reverse

#define amxc_llist_for_each_reverse (   it,
  list 
)
Value:
* it ## _prev = amxc_llist_it_get_previous(it); \
it; \
it = it ## _prev, \
AMXC_INLINE amxc_llist_it_t * amxc_llist_it_get_previous(const amxc_llist_it_t *const reference)
Gets the previous iterator in the list.
Definition: amxc_llist.h:842
AMXC_INLINE amxc_llist_it_t * amxc_llist_get_last(const amxc_llist_t *const llist)
Gets the last item of the linked list.
Definition: amxc_llist.h:732

Loops over the list from tail to head.

Iterates over the list and updates the iterator each time.

Warning
Do not modify the list itself while using this macro. It is possible to nest this macro It is allowed to delete or remove the current iterator from the list.

Definition at line 287 of file amxc_llist.h.

◆ amxc_llist_iterate

#define amxc_llist_iterate (   it,
  list 
)
Value:

Loops over the list from head to tail.

Iterates over the list and updates the iterator each time.

Warning
Do not modify the list itself while using this macro.

Definition at line 270 of file amxc_llist.h.

◆ amxc_llist_iterate_reverse

#define amxc_llist_iterate_reverse (   it,
  list 
)
Value:

Loops over the list from tail to head.

Iterates over the list and updates the iterator each time.

Warning
Do not modify the list itself while using this macro.

Definition at line 304 of file amxc_llist.h.

Typedef Documentation

◆ amxc_llist_it_delete_t

typedef void(* amxc_llist_it_delete_t) (amxc_llist_it_t *it)

Definition of the linked list item delete function.

A pointer to a delete function is used in the following functions amxc_llist_delete, amxc_llist_clean, amxc_llist_it_clean.

Definition at line 317 of file amxc_llist.h.

◆ amxc_llist_t

typedef struct _amxc_llist amxc_llist_t

The linked list structure.

Function Documentation

◆ amxc_llist_append()

int amxc_llist_append ( amxc_llist_t *const  llist,
amxc_llist_it_t *const  it 
)

Adds an item to the end of the linked list.

If the item is already in a list, it is removed from that list.

Note
Make sure that the iterator of the item is at least initialized when it is first used. Initializing an iterator can be done using amxc_llist_it_init. An iterator that is already used in a linked list is considered initialized.
Parameters
llista pointer to the linked list structure
ita pointer to the linked list item iterator
Returns
returns 0 when the item is added, -1 when there was an error

Definition at line 169 of file amxc_llist.c.

169  {
170  int retval = -1;
171  when_null(llist, exit);
172  when_null(it, exit);
173 
174  if(it->llist != NULL) {
176  }
177 
178  it->llist = llist;
179  it->prev = llist->tail;
180  it->next = NULL;
181 
182  if(llist->tail != NULL) {
183  llist->tail->next = it;
184  llist->tail = it;
185  } else {
186  llist->tail = it;
187  llist->head = it;
188  }
189 
190  retval = 0;
191 
192 exit:
193  return retval;
194 }
#define when_null(x, l)
Definition: amxc_macros.h:126
void amxc_llist_it_take(amxc_llist_it_t *const it)
Removes the iterator from the list.
amxc_htable_it_t * next
Definition: amxc_htable.h:141
struct _amxc_llist_it * next
Definition: amxc_llist.h:216
amxc_llist_it_t * head
Definition: amxc_llist.h:229
amxc_llist_it_t * tail
Definition: amxc_llist.h:230
static amxc_llist_t * llist

◆ amxc_llist_clean()

void amxc_llist_clean ( amxc_llist_t *const  llist,
amxc_llist_it_delete_t  func 
)

Removes all items from the linked list.

Removes all items from the linked list, if a delete function is provided, it is called for each item after it was removed from the list.

Parameters
llista pointer to the linked list structure
funca pointer to a function that is called to free each item in the linked list

Definition at line 124 of file amxc_llist.c.

124  {
125  amxc_llist_it_t* it = llist != NULL ? llist->head : NULL;
126  while(it != NULL) {
128  if(func != NULL) {
129  func(it);
130  }
131  it = llist->head;
132  }
133 }

◆ amxc_llist_delete()

void amxc_llist_delete ( amxc_llist_t **  llist,
amxc_llist_it_delete_t  func 
)

Frees the previously allocated linked list.

Removes all items from the linked list, if a delete function is provided, it is called for each item after it was removed from the list.

Frees the allocated memory and sets the pointer to NULL.

Note
Only call this function for linked lists that are allocated on the heap using amxc_llist_new
Parameters
llista pointer to the location where the pointer to the linked list is stored
funca pointer to a function that is called to free each item in the linked list

Definition at line 101 of file amxc_llist.c.

101  {
102  when_null(llist, exit);
103 
104  amxc_llist_clean(*llist, func);
105  free(*llist);
106  *llist = NULL;
107 exit:
108  return;
109 }

◆ amxc_llist_get_at()

amxc_llist_it_t* amxc_llist_get_at ( const amxc_llist_t *const  llist,
const unsigned int  index 
)

Gets an item at a certain position of the linked list.

This function is not removing the item from the linked list. To remove the item from the linked list use amxc_llist_take_at.

Note
This function loops over the linked list, counting each item until the desired index is reached. Avoid to use this function for big linked lists, it can have a huge impact on performance. Use amxc_llist_get_last to get the last item in the list and not this function.
Parameters
llista pointer to the linked list structure
indexthe position of the item to get
Returns
Returns the iterator of the linked list item at the requested index, or NULL when there is no such item.

Definition at line 222 of file amxc_llist.c.

223  {
224  amxc_llist_it_t* it = NULL;
225  size_t count = 0;
226 
227  for(it = llist != NULL ? llist->head : NULL; it; it = it->next) {
228  if(count == index) {
229  break;
230  }
231  count++;
232  }
233 
234  return it;
235 }

◆ amxc_llist_get_first()

AMXC_INLINE amxc_llist_it_t* amxc_llist_get_first ( const amxc_llist_t *const  llist)

Gets the first item of the linked list.

This function does not remove the item from the linked list. To remove the item, use amxc_llist_take_first.

Parameters
llista pointer to the linked list structure
Returns
Returns the first iterator of the linked list, or NULL when the linked list is empty.

Definition at line 713 of file amxc_llist.h.

713  {
714  return llist != NULL ? llist->head : NULL;
715 }

◆ amxc_llist_get_last()

AMXC_INLINE amxc_llist_it_t* amxc_llist_get_last ( const amxc_llist_t *const  llist)

Gets the last item of the linked list.

This function does not remove the item from the linked list. To remove the item, use amxc_llist_take_last.

Parameters
llista pointer to the linked list structure
Returns
Returns the last iterator of the linked list, or NULL when the linked list is empty.

Definition at line 732 of file amxc_llist.h.

732  {
733  return llist != NULL ? llist->tail : NULL;
734 }

◆ amxc_llist_init()

int amxc_llist_init ( amxc_llist_t *const  llist)

Initializes a linked list.

Initializes the linked list structure. All pointers are reset to NULL. This function is typically called for linked lists that are on the stack. Allocating and initializing a linked list on the heap can be done using amxc_llist_new

Note
When calling this function on an already initialized linked list, that contains items, the linked list is reset and all items in the list are lost. Use amxc_llist_clean to remove all items from the list.
Parameters
llista pointer to the linked list structure.
Returns
0 on success. -1 if a NULL pointer is given.

Definition at line 111 of file amxc_llist.c.

111  {
112  int retval = -1;
113  when_null(llist, exit);
114 
115  llist->head = NULL;
116  llist->tail = NULL;
117 
118  retval = 0;
119 
120 exit:
121  return retval;
122 }

◆ amxc_llist_is_empty()

bool amxc_llist_is_empty ( const amxc_llist_t *const  llist)

Checks that the linked list is empty.

Parameters
llista pointer to the linked list structure
Returns
returns true when the linked list contains no items, false when there is at least one item in the list.

Definition at line 165 of file amxc_llist.c.

165  {
166  return llist != NULL ? (llist->head == NULL) : true;
167 }

◆ amxc_llist_move()

int amxc_llist_move ( amxc_llist_t *const  dest,
amxc_llist_t *const  src 
)

Moves all items from one linked list to another linked list.

After the move the source linked list will be empty.

If the destination linked list already contains items, the items of the source are appended to the destination linked list.

Note
Moving items from one linked list to another linked list can not fail.
Parameters
desta pointer to the destination linked list
srca pointer to the source linked list
Returns
Always 0.

Definition at line 135 of file amxc_llist.c.

135  {
136  int retval = -1;
137 
138  when_null(dest, exit);
139  when_null(src, exit);
140 
141  amxc_llist_for_each(it, src) {
142  amxc_llist_append(dest, it);
143  }
144 
145  retval = 0;
146 
147 exit:
148  return retval;
149 }

◆ amxc_llist_new()

int amxc_llist_new ( amxc_llist_t **  llist)

Allocates a linked list.

Allocates and initializes memory to store a linked list. This function allocates memory from the heap, if a linked list is on the stack, it can be initialized using function amxc_llist_init

Note
The allocated memory must be freed when not used anymore, use amxc_llist_delete to free the memory
Parameters
llista pointer to the location where the pointer to the new linked list can be stored
Returns
-1 if an error occured. 0 on success

Definition at line 88 of file amxc_llist.c.

88  {
89  int retval = -1;
90  when_null(llist, exit);
91 
92  *llist = (amxc_llist_t*) calloc(1, sizeof(amxc_llist_t));
93  when_null(*llist, exit);
94 
95  retval = 0;
96 
97 exit:
98  return retval;
99 }

◆ amxc_llist_prepend()

int amxc_llist_prepend ( amxc_llist_t *const  llist,
amxc_llist_it_t *const  it 
)

Adds an item to the beginning of the linked list.

If the item is already in a list, it is removed from that list.

Note
Make sure that the iterator of the item is at least initialized when it is first used. Initializing an iterator can be done using amxc_llist_it_init. An iterator that is already used in a linked list is considered initialized.
Parameters
llista pointer to the linked list structure
ita pointer to the linked list item iterator
Returns
returns 0 when the item is added, -1 when there was an error

Definition at line 196 of file amxc_llist.c.

196  {
197  int retval = -1;
198  when_null(llist, exit);
199  when_null(it, exit);
200 
201  if(it->llist != NULL) {
203  }
204 
205  it->llist = llist;
206  it->next = llist->head;
207  it->prev = NULL;
208 
209  if(llist->head != NULL) {
210  llist->head->prev = it;
211  llist->head = it;
212  } else {
213  llist->tail = it;
214  llist->head = it;
215  }
216 
217  retval = 0;
218 exit:
219  return retval;
220 }
struct _amxc_llist_it * prev
Definition: amxc_llist.h:218

◆ amxc_llist_set_at()

int amxc_llist_set_at ( amxc_llist_t llist,
const unsigned int  index,
amxc_llist_it_t *const  it 
)

Inserts an item at a certain position.

If the item is already in a list, it is removed from that list. If the index is out of range (higher then number of items in the linked list) the item is not added.

Note
This function loops over the linked list, counting each item until the desired index is reached. The item is inserted before the found item. Avoid to use this function for big linked lists, it can have a huge impact on performance. Use amxc_llist_append to add an item at the end of the list and not this function.
Parameters
llista pointer to the linked list structure
indexthe position where the item must be inserted
ita pointer to the linked list item iterator
Returns
returns 0 when the item is added, -1 when there was an error

Definition at line 237 of file amxc_llist.c.

239  {
240  int retval = -1;
241  amxc_llist_it_t* reference = NULL;
242 
243  size_t count = 0;
244 
245  for(reference = llist != NULL ? llist->head : NULL;
246  reference;
247  reference = reference->next) {
248  if(count == index) {
249  break;
250  }
251  count++;
252  }
253 
254  if(!reference && (index == count)) {
255  retval = amxc_llist_append(llist, it);
256  } else {
257  retval = amxc_llist_it_insert_before(reference, it);
258  }
259  return retval;
260 }
int amxc_llist_it_insert_before(amxc_llist_it_t *const reference, amxc_llist_it_t *const it)
Inserts an iterator before a reference interator in the list.

◆ amxc_llist_size()

size_t amxc_llist_size ( const amxc_llist_t *const  llist)

Calculates the size of the linked list.

Loops over all items in the linked list and counts them. The size of the linked list is expressed in items.

Note
Use amxc_llist_is_empty to check if a list is empty, do not use this function to check if the list is empty
Parameters
llista pointer to the linked list structure
Returns
returns the number of items in linked list

Definition at line 151 of file amxc_llist.c.

151  {
152  size_t count = 0;
153 
154  // no check on null pointer is needed here.
155  // amxc_llist_first will return null anyway.
156  for(amxc_llist_it_t* it = llist != NULL ? llist->head : NULL;
157  it != NULL;
158  it = it->next) {
159  count++;
160  }
161 
162  return count;
163 }

◆ amxc_llist_sort()

int amxc_llist_sort ( amxc_llist_t *const  llist,
amxc_llist_it_cmp_t  cmp 
)

Sorts a linked list.

Using a callback compare function, the items in the linked list are sorted. The callback function must match amxc_llist_it_cmp_t signature.

Parameters
llista pointer to the linked list
cmpthe sort compare callback function
Returns
0 when sort is done successful, any other value when sorting fails.

Definition at line 262 of file amxc_llist.c.

262  {
263  int retval = -1;
264  when_null(llist, exit);
265  when_null(cmp, exit);
266 
268  retval = 0;
269  goto exit;
270  }
271 
272  retval = amxc_llist_sort_internal(llist, cmp);
273 
274 exit:
275  return retval;
276 }
static int amxc_llist_sort_internal(amxc_llist_t *const llist, amxc_llist_it_cmp_t cmp)
Definition: amxc_llist.c:66
bool amxc_llist_is_empty(const amxc_llist_t *const llist)
Checks that the linked list is empty.
Definition: amxc_llist.c:165

◆ amxc_llist_take_at()

AMXC_INLINE amxc_llist_it_t* amxc_llist_take_at ( const amxc_llist_t llist,
const unsigned int  index 
)

Removes an item at a certain position of the linked list.

This function removes the item from the linked list. To get a pointer to the item, without removing it, use amxc_llist_get_at.

Note
This function loops over the linked list, counting each item until the desired index is reached. Avoid to use this function for big linked lists, it can have a huge impact on performance. Use amxc_llist_take_last to remove the last item from the list and not this function.
Parameters
llista pointer to the linked list structure
indexthe position of the item to get
Returns
Returns the iterator of the linked list item at the requested index, or NULL when there is no such item.

Definition at line 803 of file amxc_llist.h.

804  {
807  return it;
808 }
amxc_llist_it_t * amxc_llist_get_at(const amxc_llist_t *const llist, const unsigned int index)
Gets an item at a certain position of the linked list.
Definition: amxc_llist.c:222

◆ amxc_llist_take_first()

AMXC_INLINE amxc_llist_it_t* amxc_llist_take_first ( amxc_llist_t *const  llist)

Removes the first item from the linked list.

This function removes the item from the linked list. To get the item without removing it from the list use amxc_llist_get_first.

Parameters
llista pointer to the linked list structure
Returns
Returns the first iterator of the linked list, or NULL when the linked list is empty.

Definition at line 752 of file amxc_llist.h.

752  {
755  return it;
756 }

◆ amxc_llist_take_last()

AMXC_INLINE amxc_llist_it_t* amxc_llist_take_last ( amxc_llist_t *const  llist)

Removes the last item from the linked list.

This function removes the item from the linked list. To get the item without removing it from the list use amxc_llist_get_last.

Parameters
llista pointer to the linked list structure
Returns
Returns the last iterator of the linked list, or NULL when the linked list is empty.

Definition at line 774 of file amxc_llist.h.

774  {
777  return it;
778 }