]> git.ipfire.org Git - thirdparty/strongswan.git/blame - programs/charon/lib/utils/linked_list.c
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / charon / lib / utils / linked_list.c
CommitLineData
be910ee4
JH
1/**
2 * @file linked_list.c
79538669 3 *
51ecb022 4 * @brief Implementation of linked_list_t.
79538669 5 *
be910ee4
JH
6 */
7
8/*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23#include <stdlib.h>
be910ee4
JH
24
25#include "linked_list.h"
79538669 26
be910ee4 27
d794bcdb 28
5796aa16 29typedef struct linked_list_element_t linked_list_element_t;
7c2228f1
JH
30
31/**
d794bcdb 32 * @brief Element in a linked list.
79538669 33 *
d794bcdb 34 * This element holds a pointer to the value it represents.
7c2228f1 35 */
5796aa16 36struct linked_list_element_t {
d794bcdb 37
7c2228f1 38 /**
e0e554ca 39 * Value of a list item.
7c2228f1 40 */
e3dd1393 41 void *value;
79538669 42
7c2228f1 43 /**
d794bcdb
JH
44 * Previous list element.
45 *
46 * NULL if first element in list.
7c2228f1 47 */
e3dd1393 48 linked_list_element_t *previous;
d048df5c 49
7c2228f1 50 /**
d794bcdb
JH
51 * Next list element.
52 *
53 * NULL if last element in list.
7c2228f1 54 */
e3dd1393 55 linked_list_element_t *next;
d048df5c
MW
56
57 /**
58 * Destroys a linked_list_element object.
59 *
d794bcdb 60 * @param linked_list_element_t calling object
d048df5c
MW
61 */
62 void (*destroy) (linked_list_element_t *this);
7c2228f1
JH
63};
64
be910ee4 65/**
e0e554ca 66 * Implementation of linked_list_element_t.destroy.
be910ee4 67 */
d048df5c 68static void linked_list_element_destroy(linked_list_element_t *this)
be910ee4 69{
5113680f 70 free(this);
be910ee4
JH
71}
72
e3dd1393 73/**
e0e554ca 74 * @brief Creates an empty linked list object.
e3dd1393 75 *
e0e554ca
JH
76 * @warning Only the pointer to the value is stored.
77 *
d794bcdb
JH
78 * @param[in] value value of item to be set
79 * @return linked_list_element_t object
adca27eb 80 */
e3dd1393 81
be910ee4
JH
82linked_list_element_t *linked_list_element_create(void *value)
83{
5113680f 84 linked_list_element_t *this = malloc_thing(linked_list_element_t);
79538669 85
623fec54 86 this->destroy = linked_list_element_destroy;
79538669 87
be910ee4
JH
88 this->previous=NULL;
89 this->next=NULL;
e3dd1393 90 this->value = value;
79538669 91
e3dd1393 92 return (this);
7c2228f1
JH
93}
94
e0e554ca
JH
95
96typedef struct private_linked_list_t private_linked_list_t;
d794bcdb 97
7c2228f1 98/**
d794bcdb 99 * Private data of a linked_list_t object.
79538669 100 *
7c2228f1 101 */
5796aa16 102struct private_linked_list_t {
7c2228f1 103 /**
e0e554ca 104 * Public part of linked list.
7c2228f1
JH
105 */
106 linked_list_t public;
79538669 107
7c2228f1 108 /**
e0e554ca 109 * Number of items in the list.
7c2228f1
JH
110 */
111 int count;
79538669 112
7c2228f1 113 /**
e0e554ca
JH
114 * First element in list.
115 * NULL if no elements in list.
7c2228f1 116 */
e3dd1393 117 linked_list_element_t *first;
d048df5c 118
7c2228f1 119 /**
e0e554ca
JH
120 * Last element in list.
121 * NULL if no elements in list.
7c2228f1 122 */
e3dd1393 123 linked_list_element_t *last;
7c2228f1
JH
124};
125
126
e0e554ca
JH
127typedef struct private_iterator_t private_iterator_t;
128
7c2228f1 129/**
e0e554ca 130 * Private variables and functions of linked list iterator.
7c2228f1 131 */
bdb141cb 132struct private_iterator_t {
7c2228f1 133 /**
e0e554ca 134 * Public part of linked list iterator.
7c2228f1 135 */
bdb141cb 136 iterator_t public;
79538669 137
7c2228f1 138 /**
e0e554ca 139 * Associated linked list.
7c2228f1
JH
140 */
141 private_linked_list_t * list;
79538669 142
7c2228f1 143 /**
e0e554ca 144 * Current element of the iterator.
7c2228f1 145 */
e3dd1393 146 linked_list_element_t *current;
7c2228f1
JH
147
148 /**
e0e554ca 149 * Direction of iterator.
7c2228f1
JH
150 */
151 bool forward;
152};
153
154/**
e0e554ca 155 * Implementation of iterator_t.has_next.
7c2228f1 156 */
dfa6e086
MW
157static bool iterate(private_iterator_t *this, void** value)
158{
159 if (this->list->count == 0)
160 {
161 return FALSE;
162 }
163 if (this->current == NULL)
164 {
165 this->current = (this->forward) ? this->list->first : this->list->last;
166 *value = this->current->value;
167 return TRUE;
168 }
169 if (this->forward)
170 {
171 if (this->current->next == NULL)
172 {
173 return FALSE;
174 }
175 this->current = this->current->next;
176 *value = this->current->value;
177 return TRUE;
178 }
179 /* backward */
180 if (this->current->previous == NULL)
181 {
182 return FALSE;
183 }
184 this->current = this->current->previous;
185 *value = this->current->value;
186 return TRUE;
187}
188
189/**
190 * Implementation of iterator_t.has_next.
191 */
192static bool iterator_has_next(private_iterator_t *this)
7c2228f1
JH
193{
194 if (this->list->count == 0)
195 {
e3dd1393 196 return FALSE;
7c2228f1
JH
197 }
198 if (this->current == NULL)
199 {
200 this->current = (this->forward) ? this->list->first : this->list->last;
79538669 201 return TRUE;
7c2228f1
JH
202 }
203 if (this->forward)
204 {
205 if (this->current->next == NULL)
206 {
e3dd1393 207 return FALSE;
7c2228f1
JH
208 }
209 this->current = this->current->next;
79538669 210 return TRUE;
7c2228f1 211 }
79538669 212 /* backward */
7c2228f1
JH
213 if (this->current->previous == NULL)
214 {
e3dd1393 215 return FALSE;
7c2228f1
JH
216 }
217 this->current = this->current->previous;
79538669 218 return TRUE;
7c2228f1
JH
219}
220
221/**
e0e554ca 222 * Implementation of iterator_t.current.
7c2228f1 223 */
bdb141cb 224static status_t iterator_current(private_iterator_t *this, void **value)
7c2228f1 225{
e3dd1393
JH
226 if (this->current == NULL)
227 {
e0e554ca 228 return NOT_FOUND;
e3dd1393
JH
229 }
230 *value = this->current->value;
7c2228f1
JH
231 return SUCCESS;
232}
233
234/**
e0e554ca 235 * Implementation of iterator_t.reset.
7c2228f1 236 */
d048df5c 237static void iterator_reset(private_iterator_t *this)
7c2228f1 238{
e0e554ca 239 this->current = NULL;
e0e554ca
JH
240}
241
242/**
243 * Implementation of iterator_t.remove.
244 */
245static status_t remove(private_iterator_t *this)
246{
247 linked_list_element_t *new_current;
248
249 if (this->current == NULL)
e3dd1393 250 {
e0e554ca 251 return NOT_FOUND;
e3dd1393 252 }
e0e554ca
JH
253
254 if (this->list->count == 0)
255 {
256 return NOT_FOUND;
257 }
258 /* find out the new iterator position */
1e54ebfa 259 if (this->current->previous != NULL)
e0e554ca
JH
260 {
261 new_current = this->current->previous;
262 }
263 else if (this->current->next != NULL)
264 {
265 new_current = this->current->next;
266 }
267 else
268 {
269 new_current = NULL;
270 }
271
272 /* now delete the entry :-) */
273 if (this->current->previous == NULL)
274 {
275 if (this->current->next == NULL)
276 {
277 this->list->first = NULL;
278 this->list->last = NULL;
279 }
280 else
281 {
282 this->current->next->previous = NULL;
283 this->list->first = this->current->next;
284 }
285 }
286 else if (this->current->next == NULL)
287 {
288 this->current->previous->next = NULL;
289 this->list->last = this->current->previous;
290 }
291 else
292 {
293 this->current->previous->next = this->current->next;
294 this->current->next->previous = this->current->previous;
295 }
296
297 this->list->count--;
298 this->current->destroy(this->current);
299 /* set the new iterator position */
300 this->current = new_current;
7c2228f1
JH
301 return SUCCESS;
302}
303
304/**
e0e554ca 305 * Implementation of iterator_t.insert_before.
7c2228f1 306 */
d048df5c 307static void insert_before(private_iterator_t * iterator, void *item)
7c2228f1 308{
e0e554ca
JH
309 if (iterator->current == NULL)
310 {
d048df5c 311 iterator->list->public.insert_first(&(iterator->list->public), item);
e0e554ca
JH
312 }
313
314 linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
315
e0e554ca
JH
316 if (iterator->current->previous == NULL)
317 {
e0e554ca
JH
318 iterator->current->previous = element;
319 element->next = iterator->current;
320 iterator->list->first = element;
321 }
322 else
323 {
324 iterator->current->previous->next = element;
325 element->previous = iterator->current->previous;
326 iterator->current->previous = element;
327 element->next = iterator->current;
328 }
329
330 iterator->list->count++;
e0e554ca
JH
331}
332
d440fe6d
JH
333/**
334 * Implementation of iterator_t.replace.
335 */
68621281 336static status_t replace (private_iterator_t *this, void **old_item, void *new_item)
d440fe6d
JH
337{
338 if (this->current == NULL)
339 {
340 return NOT_FOUND;
341 }
342 if (old_item != NULL)
343 {
344 *old_item = this->current->value;
345 }
346 this->current->value = new_item;
347
348 return SUCCESS;
349}
350
e0e554ca
JH
351/**
352 * Implementation of iterator_t.insert_after.
353 */
d048df5c 354static void insert_after(private_iterator_t * iterator, void *item)
e0e554ca
JH
355{
356 if (iterator->current == NULL)
357 {
d048df5c 358 iterator->list->public.insert_first(&(iterator->list->public),item);
c6ec246d 359 return;
e0e554ca
JH
360 }
361
362 linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
363
e0e554ca
JH
364 if (iterator->current->next == NULL)
365 {
e0e554ca
JH
366 iterator->current->next = element;
367 element->previous = iterator->current;
368 iterator->list->last = element;
369 }
370 else
371 {
372 iterator->current->next->previous = element;
373 element->next = iterator->current->next;
374 iterator->current->next = element;
375 element->previous = iterator->current;
e3dd1393 376 }
e0e554ca 377 iterator->list->count++;
e0e554ca
JH
378}
379
380/**
381 * Implementation of iterator_t.destroy.
382 */
d048df5c 383static void iterator_destroy(private_iterator_t *this)
e0e554ca 384{
5113680f 385 free(this);
7c2228f1
JH
386}
387
388/**
e0e554ca 389 * Implementation of linked_list_t.get_count.
7c2228f1 390 */
1061c878 391static int get_count(private_linked_list_t *this)
7c2228f1 392{
1061c878 393 return this->count;
7c2228f1
JH
394}
395
c06dbbab
MW
396/**
397 * Implementation of linked_list_t.call_on_items.
398 */
399static void call_on_items(private_linked_list_t *this, void(*func)(void*))
400{
401 iterator_t *iterator;
402 void *item;
403
404 iterator = this->public.create_iterator(&(this->public),TRUE);
405
406 while (iterator->has_next(iterator))
407 {
408 iterator->current(iterator, &item);
409 (*func)(item);
410 }
411 iterator->destroy(iterator);
412}
7c2228f1 413
be910ee4 414/**
e0e554ca 415 * Implementation of linked_list_t.insert_first.
be910ee4 416 */
d048df5c 417static void insert_first(private_linked_list_t *this, void *item)
be910ee4 418{
e3dd1393 419 linked_list_element_t *element;
79538669 420
e3dd1393 421 element =(linked_list_element_t *) linked_list_element_create(item);
79538669 422
be910ee4
JH
423 if (this->count == 0)
424 {
425 /* first entry in list */
426 this->first = element;
427 this->last = element;
428 element->previous = NULL;
429 element->next = NULL;
dc64bed1
JH
430 }
431 else
be910ee4 432 {
e3dd1393 433 linked_list_element_t *old_first_element = this->first;
be910ee4 434 element->next = old_first_element;
7c2228f1 435 element->previous = NULL;
be910ee4
JH
436 old_first_element->previous = element;
437 this->first = element;
438 }
79538669 439
be910ee4 440 this->count++;
be910ee4
JH
441}
442
443/**
e0e554ca 444 * Implementation of linked_list_t.remove_first.
be910ee4 445 */
7c2228f1 446static status_t remove_first(private_linked_list_t *this, void **item)
79538669 447{
be910ee4
JH
448 if (this->count == 0)
449 {
e0e554ca 450 return NOT_FOUND;
be910ee4 451 }
79538669 452
e3dd1393 453 linked_list_element_t *element = this->first;
79538669 454
be910ee4
JH
455 if (element->next != NULL)
456 {
457 element->next->previous = NULL;
458 }
459 this->first = element->next;
460
c06dbbab
MW
461 if (item != NULL)
462 {
463 *item = element->value;
464 }
be910ee4
JH
465
466 this->count--;
79538669 467
d048df5c
MW
468 element->destroy(element);
469
470 return SUCCESS;
be910ee4
JH
471}
472
473/**
e0e554ca 474 * Implementation of linked_list_t.get_first.
be910ee4 475 */
7c2228f1 476static status_t get_first(private_linked_list_t *this, void **item)
79538669 477{
be910ee4
JH
478 if (this->count == 0)
479 {
e0e554ca 480 return NOT_FOUND;
be910ee4 481 }
79538669 482
e3dd1393 483 *item = this->first->value;
be910ee4
JH
484
485 return SUCCESS;
486}
487
488/**
e0e554ca 489 * Implementation of linked_list_t.insert_last.
be910ee4 490 */
d048df5c 491static void insert_last(private_linked_list_t *this, void *item)
be910ee4 492{
e3dd1393 493 linked_list_element_t *element = (linked_list_element_t *) linked_list_element_create(item);
79538669 494
be910ee4
JH
495 if (this->count == 0)
496 {
497 /* first entry in list */
498 this->first = element;
499 this->last = element;
500 element->previous = NULL;
501 element->next = NULL;
d048df5c
MW
502 }
503 else
be910ee4 504 {
d048df5c 505
e3dd1393 506 linked_list_element_t *old_last_element = this->last;
be910ee4 507 element->previous = old_last_element;
7c2228f1 508 element->next = NULL;
be910ee4
JH
509 old_last_element->next = element;
510 this->last = element;
511 }
79538669 512
be910ee4 513 this->count++;
be910ee4
JH
514}
515
516/**
e0e554ca 517 * Implementation of linked_list_t.remove_last.
be910ee4 518 */
7c2228f1 519static status_t remove_last(private_linked_list_t *this, void **item)
79538669 520{
be910ee4
JH
521 if (this->count == 0)
522 {
e0e554ca 523 return NOT_FOUND;
be910ee4 524 }
79538669 525
e3dd1393 526 linked_list_element_t *element = this->last;
79538669 527
be910ee4
JH
528 if (element->previous != NULL)
529 {
530 element->previous->next = NULL;
531 }
532 this->last = element->previous;
533
c06dbbab
MW
534 if (item != NULL)
535 {
536 *item = element->value;
537 }
be910ee4
JH
538
539 this->count--;
79538669 540
d048df5c
MW
541 element->destroy(element);
542
543 return SUCCESS;
be910ee4
JH
544}
545
1e54ebfa
JH
546/**
547 * Implementation of linked_list_t.insert_at_position.
548 */
549static status_t insert_at_position (private_linked_list_t *this,size_t position, void *item)
550{
551 linked_list_element_t *current_element;
552 int i;
553
554 if (this->count <= position)
555 {
556 return INVALID_ARG;
557 }
558
559 current_element = this->first;
560
561 for (i = 0; i < position;i++)
562 {
563 current_element = current_element->next;
564 }
565
566 if (current_element == NULL)
567 {
568 this->public.insert_last(&(this->public),item);
569 return SUCCESS;
570 }
571
572 linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
573
574
575 if (current_element->previous == NULL)
576 {
577 current_element->previous = element;
578 element->next = current_element;
579 this->first = element;
580 }
581 else
582 {
583 current_element->previous->next = element;
584 element->previous = current_element->previous;
585 current_element->previous = element;
586 element->next = current_element;
587 }
588
589
590 this->count++;
591 return SUCCESS;
592}
593
594/**
595 * Implementation of linked_list_t.remove_at_position.
596 */
597static status_t remove_at_position (private_linked_list_t *this,size_t position, void **item)
598{
599 iterator_t *iterator;
600 int i;
601
602 if (this->count <= position)
603 {
604 return INVALID_ARG;
605 }
606
607 iterator = this->public.create_iterator(&(this->public),TRUE);
608
609 iterator->has_next(iterator);
610 for (i = 0; i < position;i++)
611 {
612 iterator->has_next(iterator);
613 }
614 iterator->current(iterator,item);
615 iterator->remove(iterator);
616 iterator->destroy(iterator);
617
618 return SUCCESS;
619}
620
621/**
622 * Implementation of linked_list_t.get_at_position.
623 */
624static status_t get_at_position (private_linked_list_t *this,size_t position, void **item)
625{
626 int i;
627 iterator_t *iterator;
628 status_t status;
629 if (this->count <= position)
630 {
631 return INVALID_ARG;
632 }
633
634 iterator = this->public.create_iterator(&(this->public),TRUE);
635
636 iterator->has_next(iterator);
637 for (i = 0; i < position;i++)
638 {
639 iterator->has_next(iterator);
640 }
641 status = iterator->current(iterator,item);
642 iterator->destroy(iterator);
643 return status;
644}
645
be910ee4 646/**
e0e554ca 647 * Implementation of linked_list_t.get_last.
be910ee4 648 */
7c2228f1 649static status_t get_last(private_linked_list_t *this, void **item)
be910ee4 650{
be910ee4
JH
651 if (this->count == 0)
652 {
e0e554ca 653 return NOT_FOUND;
be910ee4 654 }
79538669 655
e3dd1393 656 *item = this->last->value;
be910ee4
JH
657
658 return SUCCESS;
659}
660
bfdc5c7c 661/**
e0e554ca 662 * Implementation of linked_list_t.create_iterator.
bfdc5c7c 663 */
a0753941 664static iterator_t *create_iterator (private_linked_list_t *linked_list,bool forward)
12c3e4c8 665{
5113680f 666 private_iterator_t *this = malloc_thing(private_iterator_t);
12c3e4c8 667
dfa6e086 668 this->public.iterate = (bool (*) (iterator_t *this, void **value)) iterate;
bdb141cb
MW
669 this->public.has_next = (bool (*) (iterator_t *this)) iterator_has_next;
670 this->public.current = (status_t (*) (iterator_t *this, void **value)) iterator_current;
d048df5c
MW
671 this->public.insert_before = (void (*) (iterator_t *this, void *item)) insert_before;
672 this->public.insert_after = (void (*) (iterator_t *this, void *item)) insert_after;
d440fe6d 673 this->public.replace = (status_t (*) (iterator_t *, void **, void *)) replace;
bdb141cb 674 this->public.remove = (status_t (*) (iterator_t *this)) remove;
d048df5c
MW
675 this->public.reset = (void (*) (iterator_t *this)) iterator_reset;
676 this->public.destroy = (void (*) (iterator_t *this)) iterator_destroy;
12c3e4c8
MW
677
678 this->forward = forward;
679 this->current = NULL;
680 this->list = linked_list;
681
a0753941 682 return &(this->public);
bfdc5c7c
JH
683}
684
be910ee4 685/**
e0e554ca 686 * Implementation of linked_list_t.destroy.
be910ee4 687 */
d048df5c 688static void linked_list_destroy(private_linked_list_t *this)
be910ee4 689{
e0e554ca 690 void * value;
dc64bed1 691 /* Remove all list items before destroying list */
e0e554ca 692 while (this->public.remove_first(&(this->public),&value) != NOT_FOUND)
be910ee4 693 {
dc64bed1
JH
694 /* values are not destroyed so memory leaks are possible
695 * if list is not empty when deleting */
be910ee4 696 }
5113680f 697 free(this);
be910ee4 698}
79538669 699
adca27eb 700/*
d794bcdb 701 * Described in header.
adca27eb 702 */
79538669 703linked_list_t *linked_list_create()
be910ee4 704{
5113680f 705 private_linked_list_t *this = malloc_thing(private_linked_list_t);
79538669 706
1e54ebfa
JH
707 this->public.get_count = (int (*) (linked_list_t *)) get_count;
708 this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool )) create_iterator;
c06dbbab 709 this->public.call_on_items = (void (*) (linked_list_t *, void(*func)(void*)))call_on_items;
1e54ebfa
JH
710 this->public.get_first = (status_t (*) (linked_list_t *, void **item)) get_first;
711 this->public.get_last = (status_t (*) (linked_list_t *, void **item)) get_last;
712 this->public.insert_first = (void (*) (linked_list_t *, void *item)) insert_first;
713 this->public.insert_last = (void (*) (linked_list_t *, void *item)) insert_last;
714 this->public.remove_first = (status_t (*) (linked_list_t *, void **item)) remove_first;
715 this->public.remove_last = (status_t (*) (linked_list_t *, void **item)) remove_last;
716 this->public.insert_at_position =(status_t (*) (linked_list_t *,size_t, void *)) insert_at_position;
717 this->public.remove_at_position =(status_t (*) (linked_list_t *,size_t, void **)) remove_at_position;
718 this->public.get_at_position =(status_t (*) (linked_list_t *,size_t, void **)) get_at_position;
719
720 this->public.destroy = (void (*) (linked_list_t *)) linked_list_destroy;
79538669 721
be910ee4
JH
722 this->count = 0;
723 this->first = NULL;
724 this->last = NULL;
79538669 725
7c2228f1 726 return (&(this->public));
be910ee4 727}