strongswan链表结构

链表结构定义如下,public成员为公共的方法,count,first和last为私有成员,count表示链表中元素的数量,first和last分别指向链表的头和尾。public(linked_list_t结构)定义了一系列操作链表的方法,其必须为第一个结构成员,方便在公共方法和私有结构间转换。

struct private_linked_list_t {
    linked_list_t public;
    int count;
    element_t *first;
    element_t *last;
};

链表元素结构element_t如下,包括值value,和指向前一个(previous)和后一个元素(next)的两个指针:

struct element_t {
    void *value;
    element_t *previous;
    element_t *next;
};

如下函数创建通用的链表元素结构。

static element_t *element_create(void *value)
{
    element_t *this;
    INIT(this,
        .value = value,
    );
    return this;
}

创建新链表

创建新的链表,实例化链表结构,这里主要初始化了链表的公共方法,没有初始化私有成员。

linked_list_t *linked_list_create()
{
    private_linked_list_t *this;
    INIT(this,
        .public = {
            .get_count = _get_count,
            .create_enumerator = _create_enumerator,
            .reset_enumerator = (void*)_reset_enumerator,
            .get_first = _get_first,
            .get_last = _get_last,
            .find_first = _find_first,
            .insert_first = _insert_first,
            .insert_last = _insert_last,
            .insert_before = (void*)_insert_before,
            ...
        },
    );
    return &this->public;

链表元素操作

向链表尾部插入元素时,对于链表为空的情况,链表成员first和last都指向此元素。对于链表非空的情况,链表中原有最后一个元素last的next指向新元素,新元素的previous指向原有最后一个元素。新元素保存为最后一个元素last。

METHOD(linked_list_t, insert_last, void, private_linked_list_t *this, void *item)
{
    element_t *element = element_create(item);
    if (this->count == 0) {    /* first entry in list */
        this->first = element;
        this->last = element;
    } else {
        element->previous = this->last;
        this->last->next = element;
        this->last = element;
    }
    this->count++;

链表起初只有一个元素(1st_elem),在尾部增加第二个元素之后如下图所示:

this->first                     this->first  |---<-------------<-------------------|
        |                                |   |                                     |   
this->last                               |   |               this->last            |   
        |                                |   |                      |              |   
   |-----------|                     |-----------|            |-----------|        |   
   |           |--pre=NULL           |           |--pre=NULL  |           |--pre---|   
   |  1st_elem |                     |  1st_elem |            |  2nd_elem |            
   |           |--next=NULL          |           |--next----->|           |--next=NULL 
   |-----------|                     |-----------|            |-----------|            

方法insert_first在链表首部插入一个元素,递增链表元素计数。

METHOD(linked_list_t, insert_first, void, private_linked_list_t *this, void *item)
{
    element_t *element = element_create(item);
    if (this->count == 0) {
        /* first entry in list */
        this->first = element;
        this->last = element;
    } else {
        element->next = this->first;
        this->first->previous = element;
        this->first = element;
    }
    this->count++;

链表起初只有一个元素(1st_elem),在首部增加第二个元素之后如下图所示:

this->first                     this->first   |---------<------<-----------------------------|                             
        |                               |     |                                              |
this->last                              |     |                     this->last               |   
        |                               |     |                             |                |   
   |-----------|                   |--------------|                 |---------------|        |     
   |           |--pre=NULL         |              |--pre=NULL       |               |--pre---|   
   |  1st_elem |                   | new_1st_elem |                 |  old_1st_elem |             
   |           |--next=NULL        |              |--next---------->|               |--next=NULL  
   |-----------|                   |--------------|                 |---------------|             

释放元素时,先行保存元素在链表中的下一个next和前一个元素previous。如果下一个元素有值,拿起previous应当指向上上个元素;否则,删除的为链表最后一个元素,previous变成最后一个元素。

如果前一个元素有值,其last应当指向下下个元素;否则,删除的为链表第一个元素,next变成第一个元素。

链表中的元素个数递减一,如果递减之后等于0,将链表的first和last指针置空。函数返回链表中被删除元素的下一个元素。

static element_t* remove_element(private_linked_list_t *this, element_t *element)
{
    element_t *next, *previous;

    next = element->next;
    previous = element->previous;
    free(element);
    if (next)
        next->previous = previous;
    else
        this->last = previous;
    if (previous)
        previous->next = next;
    else
        this->first = next;
    if (--this->count == 0){
        this->first = NULL;
        this->last = NULL;
    }
    return next;

链表枚举器

链表的枚举器结构定义如下,public成员为公共的方法,list和current为私有成员。public必须为第一个结构成员,方便在公共方法和私有结构间切换。

struct private_enumerator_t {
    enumerator_t public;
    private_linked_list_t *list;
    element_t *current;
};

枚举器结构的公共方法有以下三个。

struct enumerator_t {
    bool (*enumerate)(enumerator_t *this, ...);
    bool (*venumerate)(enumerator_t *this, va_list args);
    void (*destroy)(enumerator_t *this);
};

create_enumerator函数创建枚举器,初始化private_enumerator_t结构,链表结构实现了venumerate函数,enumerate函数使用枚举器默认的。私有成员list初始化为链表结构this,current成员指向链表首个元素。

METHOD(linked_list_t, create_enumerator, enumerator_t*, private_linked_list_t *this)
{   
    private_enumerator_t *enumerator;
    
    INIT(enumerator,
        .public = {
            .enumerate = enumerator_enumerate_default,
            .venumerate = _enumerate_current,
            .destroy = (void*)free,
        },
        .list = this,
        .current = this->first,
    );
    return &enumerator->public;

枚举器要求必须实现venumerate方法,其默认函数(enumerator_enumerate_default)是对venumerate的封装。此函数接受可变数量的参数,之后将这些参数传入venumerate方法。

bool enumerator_enumerate_default(enumerator_t *enumerator, ...)
{
    va_list args;
    bool result;

    if (!enumerator->venumerate) {
        DBG1(DBG_LIB, "!!! ENUMERATE DEFAULT: venumerate() missing !!!");
        return FALSE;
    }
    va_start(args, enumerator);
    result = enumerator->venumerate(enumerator, args);
    va_end(args);
    return result;

枚举器初始化的venumerate函数如下,在首次调用之后,其公共方法venumerate更换为_enumerate_next,用于获取枚举器的下一个元素。

METHOD(enumerator_t, enumerate_current, bool,
    private_enumerator_t *this, va_list args)
{
    this->public.venumerate = _enumerate_next;
    return do_enumerate(this, args);
}

初始化时,枚举器的current指向了链表结构的首个元素,如果current和传入参数都有效,将current元素的值赋予参数中。对于链表结构,可变参数的数量为1。

如果current为空,返回FALSE,表示整个枚举过程结束,链表结构的元素遍历完成。

static bool do_enumerate(private_enumerator_t *this, va_list args)
{   
    void **item;
    
    VA_ARGS_VGET(args, item);
    
    if (!this->current) 
        return FALSE;
    if (item)
        *item = this->current->value;
    return TRUE;

通常在遍历第二个元素时,枚举器的venumerate函数换成了enumerate_next,枚举器的私有成员current指向链表下一个元素。do_enumerate执行以上的取值操作,取出下一个链表元素。

METHOD(enumerator_t, enumerate_next, bool, private_enumerator_t *this, va_list args)
{
    if (this->current)
        this->current = this->current->next;
    return do_enumerate(this, args);
}

枚举器使用完之后,需要由reset_enumerator复位,枚举器的current再次指向链表结构的首个元素,枚举器的公共方法venumerate恢复为指向enumerate_current函数。

METHOD(linked_list_t, reset_enumerator, void,
    private_linked_list_t *this, private_enumerator_t *enumerator)
{
    enumerator->current = this->first;
    enumerator->public.venumerate = _enumerate_current;
}

strongswan-5.9.14

相关推荐
躺不平的理查德8 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
半夜不咋不困8 小时前
单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
数据结构·链表
一颗星星辰17 小时前
数据结构 | 题目练习第二章 | 合并两个有序链表 | 环形链表 | 环形链表入环第一个节点
网络·数据结构·链表
2401_8582861120 小时前
L6.【LeetCode笔记】合并两个有序链表
c语言·开发语言·笔记·leetcode·链表
攻城狮7号1 天前
【5.7】指针算法-快慢指针解决环形链表
数据结构·c++·算法·链表
passer__jw7671 天前
【LeetCode】【算法】160.相交链表
算法·leetcode·链表
大油头儿1 天前
Python 实现链表:详解与应用
python·链表
暴怒香菜统治世界2 天前
数据结构--二叉树_链式(下)
c语言·开发语言·数据结构·算法·链表
月临水2 天前
算法: 链表题目练习
数据结构·算法·链表
Charary2 天前
链表练习记录
c语言·数据结构·学习·链表