可自由转载, 转载请保留作者信息 jundai2009@gmail.com 和本初始url;
既然准备写一个稍微有点规模的软件, 基本的工具API必不可少.
本篇就说说使用的链表. 高手请跳过
首先,为什么不使用现成的库呢?
1. 本来就是兴趣项目,练习编码也是目的之一, 当然, 自己造轮子.
2. 自己实现可操作性强一点.
主要copy linux中链表的实现, 同时稍微改造下
1. 简化, 只保留本库必须的部分. 不想搞太多没用的代码, 那样也不便维护.
2. 加入排序函数指针, 换句话说, 使用有序链表
几个基本小技巧, 再次申明 高手请跳过:
#define offset_of(type, memb) \
((unsigned long)(&((type *)0)->memb))
表示结构type中memb的偏移量, 用于下面list_entry
#define list_entry(obj, type, memb) \
((type *)(((char *)obj) - offset_of(type, memb)))
obj是需要使用链表来管理的用户结构的指针, type是用户结构的定义, memb是用户结构中用于本链表连接的参数.
可以看出, 这样管理链表, 比较容易就可以支持一个结构属于多个链表的场景.
具体可以看看下面的例子,应该能很快明白.
部分代码如下:
/* list.h
* All right reserved, 2010
*/
#ifndef LIST_H
#define LIST_H
#define LIST_MAGIC 0x20100408
typedef struct list_head_ {
struct list_head_ *next;
struct list_head_ *prev;
} list_head;
/* The stand alone, real list header */
typedef struct list_header_ {
list_head list; /* must be the first element in this structure */
int count;
int list_magic;
}list_header;
#define LIST_SIZE(list) ((list)->count)
#define list_for_each(head, pos) \
for (pos = (head)->list.next; pos != &((head)->list); pos = pos->next)
#define offset_of(type, memb) \
((unsigned long)(&((type *)0)->memb))
#define list_entry(obj, type, memb) \
((type *)(((char *)obj) - offset_of(type, memb)))
typedef int (*list_compare_func_t)(list_head *, list_head *);
#endif
/* list.c
* All right reserved, 2010
*/
void list_init (list_header *list)
{
assert(list);
list->list.next = &list->list;
list->list.prev = &list->list;
list->count = 0;
list->list_magic = LIST_MAGIC;
}
/* Insert new_element after prev and before next */
void __list_add(list_head *new_elem, list_head *prev, list_head *next)
{
assert(new_elem);
assert(prev);
assert(next);
next->prev = new_elem;
new_elem->next = next;
new_elem->prev = prev;
prev->next = new_elem;
}
BOOL list_insert(list_header *list, list_head *data, list_compare_func_t func)
{
list_head *element;
int compare_result;
assert(list);
assert(data);
assert(list->list_magic == LIST_MAGIC);
if (func == NULL) {
/* By default, insert to tail of the list*/
__list_add(data, list->list.prev, &list->list);
list->count++;
return TRUE;
}
list_for_each(list, element) {
compare_result = (*func)(element, data);
if (compare_result == 0) {
/* element already in the list */
return FALSE;
} else if (compare_result > 0) {
break;
}
}
__list_add(data, element->prev, element);
list->count++;
return TRUE;
}
单元测试用例
typedef struct payload_ {
list_head list;
int val;
}payload;
int payload_sort(list_head *data1, list_head *data2)
{
payload *real1, *real2;
real1 = list_entry(data1, payload, list);
real2 = list_entry(data2, payload, list);
if ( (real1->val) > (real2->val) ) {
return 1;
} else if ((real1->val) < (real2->val) ) {
return -1;
}
return 0;
}
int main()
{
list_head *element;
list_header root;
payload real_data1, real_data2;
payload *real_data;
real_data1.val = 1;
real_data2.val = 2;
list_init(&root);
list_insert(&root, &real_data1.list, payload_sort);
list_for_each(&root, element) {
real_data = list_entry(element, payload, list);
}
}