Annotation of embedaddon/strongswan/src/libstrongswan/collections/linked_list.c, revision 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>