链表结构定义如下,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;elsethis->last = previous;if (previous)previous->next = next;elsethis->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