Annotation of embedaddon/strongswan/src/libstrongswan/collections/linked_list.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2007-2018 Tobias Brunner
3: * Copyright (C) 2005-2006 Martin Willi
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #include <stdlib.h>
19: #include <stdarg.h>
20:
21: #include "linked_list.h"
22:
23: typedef struct element_t element_t;
24:
25: /**
26: * This element holds a pointer to the value it represents.
27: */
28: struct element_t {
29:
30: /**
31: * Value of a list item.
32: */
33: void *value;
34:
35: /**
36: * Previous list element.
37: *
38: * NULL if first element in list.
39: */
40: element_t *previous;
41:
42: /**
43: * Next list element.
44: *
45: * NULL if last element in list.
46: */
47: element_t *next;
48: };
49:
50: /*
51: * Described in header
52: */
53: bool linked_list_match_str(void *item, va_list args)
54: {
55: char *a = item, *b;
56:
57: VA_ARGS_VGET(args, b);
58: return streq(a, b);
59: }
60:
61: /**
62: * Creates an empty linked list object.
63: */
64: element_t *element_create(void *value)
65: {
66: element_t *this;
67: INIT(this,
68: .value = value,
69: );
70: return this;
71: }
72:
73:
74: typedef struct private_linked_list_t private_linked_list_t;
75:
76: /**
77: * Private data of a linked_list_t object.
78: *
79: */
80: struct private_linked_list_t {
81: /**
82: * Public part of linked list.
83: */
84: linked_list_t public;
85:
86: /**
87: * Number of items in the list.
88: */
89: int count;
90:
91: /**
92: * First element in list.
93: * NULL if no elements in list.
94: */
95: element_t *first;
96:
97: /**
98: * Last element in list.
99: * NULL if no elements in list.
100: */
101: element_t *last;
102: };
103:
104: typedef struct private_enumerator_t private_enumerator_t;
105:
106: /**
107: * linked lists enumerator implementation
108: */
109: struct private_enumerator_t {
110:
111: /**
112: * implements enumerator interface
113: */
114: enumerator_t public;
115:
116: /**
117: * associated linked list
118: */
119: private_linked_list_t *list;
120:
121: /**
122: * current item
123: */
124: element_t *current;
125: };
126:
127: /**
128: * Enumerate the current item
129: */
130: static bool do_enumerate(private_enumerator_t *this, va_list args)
131: {
132: void **item;
133:
134: VA_ARGS_VGET(args, item);
135:
136: if (!this->current)
137: {
138: return FALSE;
139: }
140: if (item)
141: {
142: *item = this->current->value;
143: }
144: return TRUE;
145: }
146:
147: METHOD(enumerator_t, enumerate_next, bool,
148: private_enumerator_t *this, va_list args)
149: {
150: if (this->current)
151: {
152: this->current = this->current->next;
153: }
154: return do_enumerate(this, args);
155: }
156:
157: METHOD(enumerator_t, enumerate_current, bool,
158: private_enumerator_t *this, va_list args)
159: {
160: this->public.venumerate = _enumerate_next;
161: return do_enumerate(this, args);
162: }
163:
164: METHOD(linked_list_t, create_enumerator, enumerator_t*,
165: private_linked_list_t *this)
166: {
167: private_enumerator_t *enumerator;
168:
169: INIT(enumerator,
170: .public = {
171: .enumerate = enumerator_enumerate_default,
172: .venumerate = _enumerate_current,
173: .destroy = (void*)free,
174: },
175: .list = this,
176: .current = this->first,
177: );
178:
179: return &enumerator->public;
180: }
181:
182: METHOD(linked_list_t, reset_enumerator, void,
183: private_linked_list_t *this, private_enumerator_t *enumerator)
184: {
185: enumerator->current = this->first;
186: enumerator->public.venumerate = _enumerate_current;
187: }
188:
189: METHOD(linked_list_t, get_count, int,
190: private_linked_list_t *this)
191: {
192: return this->count;
193: }
194:
195: METHOD(linked_list_t, insert_first, void,
196: private_linked_list_t *this, void *item)
197: {
198: element_t *element;
199:
200: element = element_create(item);
201: if (this->count == 0)
202: {
203: /* first entry in list */
204: this->first = element;
205: this->last = element;
206: }
207: else
208: {
209: element->next = this->first;
210: this->first->previous = element;
211: this->first = element;
212: }
213: this->count++;
214: }
215:
216: /**
217: * unlink an element form the list, returns following element
218: */
219: static element_t* remove_element(private_linked_list_t *this,
220: element_t *element)
221: {
222: element_t *next, *previous;
223:
224: next = element->next;
225: previous = element->previous;
226: free(element);
227: if (next)
228: {
229: next->previous = previous;
230: }
231: else
232: {
233: this->last = previous;
234: }
235: if (previous)
236: {
237: previous->next = next;
238: }
239: else
240: {
241: this->first = next;
242: }
243: if (--this->count == 0)
244: {
245: this->first = NULL;
246: this->last = NULL;
247: }
248: return next;
249: }
250:
251: METHOD(linked_list_t, get_first, status_t,
252: private_linked_list_t *this, void **item)
253: {
254: if (this->count == 0)
255: {
256: return NOT_FOUND;
257: }
258: *item = this->first->value;
259: return SUCCESS;
260: }
261:
262: METHOD(linked_list_t, remove_first, status_t,
263: private_linked_list_t *this, void **item)
264: {
265: if (get_first(this, item) == SUCCESS)
266: {
267: remove_element(this, this->first);
268: return SUCCESS;
269: }
270: return NOT_FOUND;
271: }
272:
273: METHOD(linked_list_t, insert_last, void,
274: private_linked_list_t *this, void *item)
275: {
276: element_t *element;
277:
278: element = element_create(item);
279: if (this->count == 0)
280: {
281: /* first entry in list */
282: this->first = element;
283: this->last = element;
284: }
285: else
286: {
287: element->previous = this->last;
288: this->last->next = element;
289: this->last = element;
290: }
291: this->count++;
292: }
293:
294: METHOD(linked_list_t, insert_before, void,
295: private_linked_list_t *this, private_enumerator_t *enumerator,
296: void *item)
297: {
298: element_t *current, *element;
299:
300: current = enumerator->current;
301: if (!current)
302: {
303: insert_last(this, item);
304: return;
305: }
306: element = element_create(item);
307: if (current->previous)
308: {
309: current->previous->next = element;
310: element->previous = current->previous;
311: current->previous = element;
312: element->next = current;
313: }
314: else
315: {
316: current->previous = element;
317: element->next = current;
318: this->first = element;
319: }
320: this->count++;
321: }
322:
323: METHOD(linked_list_t, get_last, status_t,
324: private_linked_list_t *this, void **item)
325: {
326: if (this->count == 0)
327: {
328: return NOT_FOUND;
329: }
330: *item = this->last->value;
331: return SUCCESS;
332: }
333:
334: METHOD(linked_list_t, remove_last, status_t,
335: private_linked_list_t *this, void **item)
336: {
337: if (get_last(this, item) == SUCCESS)
338: {
339: remove_element(this, this->last);
340: return SUCCESS;
341: }
342: return NOT_FOUND;
343: }
344:
345: METHOD(linked_list_t, remove_, int,
346: private_linked_list_t *this, void *item, bool (*compare)(void*,void*))
347: {
348: element_t *current = this->first;
349: int removed = 0;
350:
351: while (current)
352: {
353: if ((compare && compare(current->value, item)) ||
354: (!compare && current->value == item))
355: {
356: removed++;
357: current = remove_element(this, current);
358: }
359: else
360: {
361: current = current->next;
362: }
363: }
364: return removed;
365: }
366:
367: METHOD(linked_list_t, remove_at, void,
368: private_linked_list_t *this, private_enumerator_t *enumerator)
369: {
370: element_t *current;
371:
372: if (enumerator->current)
373: {
374: current = enumerator->current;
375: enumerator->current = current->next;
376: /* the enumerator already points to the next item */
377: enumerator->public.venumerate = _enumerate_current;
378: remove_element(this, current);
379: }
380: }
381:
382: METHOD(linked_list_t, find_first, bool,
383: private_linked_list_t *this, linked_list_match_t match, void **item, ...)
384: {
385: element_t *current = this->first;
386: va_list args;
387: bool matched = FALSE;
388:
389: if (!match && !item)
390: {
391: return FALSE;
392: }
393:
394: while (current)
395: {
396: if (match)
397: {
398: va_start(args, item);
399: matched = match(current->value, args);
400: va_end(args);
401: }
402: else
403: {
404: matched = current->value == *item;
405: }
406: if (matched)
407: {
408: if (item != NULL)
409: {
410: *item = current->value;
411: }
412: return TRUE;
413: }
414: current = current->next;
415: }
416: return FALSE;
417: }
418:
419: METHOD(linked_list_t, invoke_offset, void,
420: private_linked_list_t *this, size_t offset)
421: {
422: element_t *current = this->first;
423: void (**method)(void*);
424:
425: while (current)
426: {
427: method = current->value + offset;
428: (*method)(current->value);
429: current = current->next;
430: }
431: }
432:
433: METHOD(linked_list_t, invoke_function, void,
434: private_linked_list_t *this, linked_list_invoke_t fn, ...)
435: {
436: element_t *current = this->first;
437: va_list args;
438:
439: while (current)
440: {
441: va_start(args, fn);
442: fn(current->value, args);
443: va_end(args);
444: current = current->next;
445: }
446: }
447:
448: METHOD(linked_list_t, clone_offset, linked_list_t*,
449: private_linked_list_t *this, size_t offset)
450: {
451: element_t *current = this->first;
452: linked_list_t *clone;
453:
454: clone = linked_list_create();
455: while (current)
456: {
457: void* (**method)(void*) = current->value + offset;
458: clone->insert_last(clone, (*method)(current->value));
459: current = current->next;
460: }
461:
462: return clone;
463: }
464:
465: METHOD(linked_list_t, equals_offset, bool,
466: private_linked_list_t *this, linked_list_t *other_pub, size_t offset)
467: {
468: private_linked_list_t *other = (private_linked_list_t*)other_pub;
469: element_t *cur_t, *cur_o;
470:
471: if (this->count != other->count)
472: {
473: return FALSE;
474: }
475: cur_t = this->first;
476: cur_o = other->first;
477: while (cur_t && cur_o)
478: {
479: bool (**method)(void*,void*) = cur_t->value + offset;
480: if (!(*method)(cur_t->value, cur_o->value))
481: {
482: return FALSE;
483: }
484: cur_t = cur_t->next;
485: cur_o = cur_o->next;
486: }
487: return TRUE;
488: }
489:
490: METHOD(linked_list_t, equals_function, bool,
491: private_linked_list_t *this, linked_list_t *other_pub,
492: bool (*fn)(void*,void*))
493: {
494: private_linked_list_t *other = (private_linked_list_t*)other_pub;
495: element_t *cur_t, *cur_o;
496:
497: if (this->count != other->count)
498: {
499: return FALSE;
500: }
501: cur_t = this->first;
502: cur_o = other->first;
503: while (cur_t && cur_o)
504: {
505: if (!fn(cur_t->value, cur_o->value))
506: {
507: return FALSE;
508: }
509: cur_t = cur_t->next;
510: cur_o = cur_o->next;
511: }
512: return TRUE;
513: }
514:
515: METHOD(linked_list_t, destroy, void,
516: private_linked_list_t *this)
517: {
518: void *value;
519:
520: /* Remove all list items before destroying list */
521: while (remove_first(this, &value) == SUCCESS)
522: {
523: /* values are not destroyed so memory leaks are possible
524: * if list is not empty when deleting */
525: }
526: free(this);
527: }
528:
529: METHOD(linked_list_t, destroy_offset, void,
530: private_linked_list_t *this, size_t offset)
531: {
532: element_t *current = this->first, *next;
533:
534: while (current)
535: {
536: void (**method)(void*) = current->value + offset;
537: (*method)(current->value);
538: next = current->next;
539: free(current);
540: current = next;
541: }
542: free(this);
543: }
544:
545: METHOD(linked_list_t, destroy_function, void,
546: private_linked_list_t *this, void (*fn)(void*))
547: {
548: element_t *current = this->first, *next;
549:
550: while (current)
551: {
552: fn(current->value);
553: next = current->next;
554: free(current);
555: current = next;
556: }
557: free(this);
558: }
559:
560: /*
561: * Described in header.
562: */
563: linked_list_t *linked_list_create()
564: {
565: private_linked_list_t *this;
566:
567: INIT(this,
568: .public = {
569: .get_count = _get_count,
570: .create_enumerator = _create_enumerator,
571: .reset_enumerator = (void*)_reset_enumerator,
572: .get_first = _get_first,
573: .get_last = _get_last,
574: .find_first = _find_first,
575: .insert_first = _insert_first,
576: .insert_last = _insert_last,
577: .insert_before = (void*)_insert_before,
578: .remove_first = _remove_first,
579: .remove_last = _remove_last,
580: .remove = _remove_,
581: .remove_at = (void*)_remove_at,
582: .invoke_offset = _invoke_offset,
583: .invoke_function = _invoke_function,
584: .clone_offset = _clone_offset,
585: .equals_offset = _equals_offset,
586: .equals_function = _equals_function,
587: .destroy = _destroy,
588: .destroy_offset = _destroy_offset,
589: .destroy_function = _destroy_function,
590: },
591: );
592:
593: return &this->public;
594: }
595:
596: /*
597: * See header.
598: */
599: linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator)
600: {
601: linked_list_t *list;
602: void *item;
603:
604: list = linked_list_create();
605:
606: while (enumerator->enumerate(enumerator, &item))
607: {
608: list->insert_last(list, item);
609: }
610: enumerator->destroy(enumerator);
611:
612: return list;
613: }
614:
615: /*
616: * See header.
617: */
618: linked_list_t *linked_list_create_with_items(void *item, ...)
619: {
620: linked_list_t *list;
621: va_list args;
622:
623: list = linked_list_create();
624:
625: va_start(args, item);
626: while (item)
627: {
628: list->insert_last(list, item);
629: item = va_arg(args, void*);
630: }
631: va_end(args);
632:
633: return list;
634: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>