本文为作者原创,转载请注明出处:http://my.oschina.net/fuckphp/blog/269685
如果需要对函数进行测试可以在源代码(src/adlist.c)下面加入以下代码,然后在main中加入你的测试代码:
#ifdef ADLIST_TEST_MAIN #include <stdio.h> int main(void) { printf("Hi\n"); return 1; } #endif
并用以下命令进行编译,并执行 ./a.out:
gcc zmalloc.c adlist.c -D ADLIST_TEST_MAIN
文章底部附了一份我自己的测试代码(按上面办法加入编译即可 编译时候参数增加 sds.c):测试代码
链表相关的头注释:
/** * 获取链表长度 * list l 链表结构 * return 返回链表的len属性 */ #define listLength(l) ((l)->len) /** * 获取链表第一个节点 * list l 链表结构 * return 返回链表的head属性 */ #define listFirst(l) ((l)->head) /** * 获取链表最后一个节点 * list l 链表结构 * return 返回链表的tail属性 */ #define listLast(l) ((l)->tail) /** * 获取链表当前节点的上一个节点 * listNode n 链表节点结构 * return 返回链表节点的prev属性 */ #define listPrevNode(n) ((n)->prev) /** * 获取链表当前节点的下一个节点 * listNode n 链表节点结构 * return 返回链表节点的next属性 */ #define listNextNode(n) ((n)->next) /** * 获取链表当前节点的值 * listNode n 链表节点结构 * return 返回链表节点的value属性 */ #define listNodeValue(n) ((n)->value) /** * 设置复制链表时候的回调函数 * list l 链表结构 * void *(*dup)(void *ptr) m 回调函数 * return void */ #define listSetDupMethod(l,m) ((l)->dup = (m)) /** * 设置释放链表时候的回调函数 * list l 链表结构 * void (*free)(void *ptr); m 回调函数 * return void */ #define listSetFreeMethod(l,m) ((l)->free = (m)) /** * 设置比较链表节点时候的回调函数 * list l 链表结构 * int (*match)(void *ptr, void *key); m 回调函数 * return void */ #define listSetMatchMethod(l,m) ((l)->match = (m)) /** * 获取复制链表时候的回调函数 * list l 链表结构 * return 复制函数的函数指针 */ #define listGetDupMethod(l) ((l)->dup) /** * 获取释放链表时候的回调函数 * list l 链表结构 * return 释放函数的函数指针 */ #define listGetFree(l) ((l)->free) /** * 获取比较链表时候的回调函数 * list l 链表结构 * return 比较函数的函数指针 */ #define listGetMatchMethod(l) ((l)->match) /** * 创建一个空的链表 * return 返回空的list指针 */ list *listCreate(void); /** * 遍历并释放所有Node节点释放节点前如果设置了free函数,则先调用free函数来释放节点的值,用来避免内存泄露 * list *list 需要释放的list结构 * return void */ void listRelease(list *list); /** * 根据 value 创建一个listNode节点,并将它加入到list链表的头部 * list *list 增加节点的list链表 * void *value listNode节点的值 * return 返回被操作的链表 */ list *listAddNodeHead(list *list, void *value); /** * 根据 value 创建一个listNode节点,并将它加入到list链表的尾部 * list *list 增加节点的list链表 * void *value listNode节点的值 * return 返回被操作的链表 */ list *listAddNodeTail(list *list, void *value) /** * 根据 value 创建一个listNode节点,并将它加入到list old_node 之后(如果after为1加old_node之后,为0加到old_node之前) * list *list 增加节点的list链表 * listNode *old_node 增加在哪个节点的旁边 * void *value listNode节点的值 * int after 如果after为1加old_node之后,为0加到old_node之前 * return 返回被操作的链表 */ list *listInsertNode(list *list, listNode *old_node, void *value, int after); /** * 将指定的节点node 在list中删除,并释放删除的node * list *list 删除节点的list链表 * listNode *node 待删除的节点 * return 返回被操作的链表 */ void listDelNode(list *list, listNode *node); /** * 复制一个list如果用户设置了dup函数,则会根据dup函数来复制每个节点的value * list *list 被复制的list * return 返回复制后的list */ list *listDup(list *orig); /** * 从list中每个节点中查找key,如果用户定义了match则根据用户的match函数来决定是否匹配 * list *list 被查找的list * void *key 用于跟list中每个节点的value进行比较 * return 找到的节点,没找到返回NULL */ listNode *listSearchKey(list *list, void *key); /** * 根据index查找对应的节点并返回 * list *list 被查找的list * int index 索引号 * return 返回对应的节点 */ listNode *listIndex(list *list, long index); /** * 将list尾部的节点移动到list的头部 * list *list 被操作的list * return void */ void listRotate(list *list);
链表迭代器相关的函数投说明:
/** * 创建一个迭代器的结构,并将迭代器指针根据direction参数来指向链表的头部或者尾部 * list *list 需要遍历的列表 * int direction 方向 AL_START_HEAD / AL_START_TAIL * return 返回迭代器listIter指针 */ listIter *listGetIterator(list *list, int direction); /** * 释放一个迭代器的结构 * listIter *iter 需要释放的迭代器结构 * return void */ void listReleaseIterator(listIter *iter); /** * 设置链表从头开始遍历(其实就是将遍历的游标指向头部) * list *list 需要设置的列表结构 * listIter *li 需要设置的迭代器 * return void */ void listRewind(list *list, listIter *li); /** * 设置链表从尾开始遍历(其实就是将遍历的游标指向尾部) * list *list 需要设置的列表结构 * listIter *li 需要更设置迭代器 * return 返回迭代器listIter指针 */ void listRewindTail(list *list, listIter *li); /** * 根据迭代器的direction获取迭代器指向的下一个及诶单 * listIter *li 用于遍历的迭代器接口 * return 返回下一个节点 */ listNode *listNext(listIter *iter);
测试代码:
#ifdef ADLIST_TEST_MAIN #include <stdio.h> #include "sds.h" void *testDup(void *ptr) { return sdsdup(ptr); } void testFree(void *ptr) { sdsfree(ptr); } int testMatch(void *ptr, void *key) { int n = 0; n = sdscmp(ptr, key) == 0 ? 1 : 0; printf("cmp: %s, %s, %d\n", ptr, key, n); return n; } int main(void) { //设置用于测试的一些临时变量 listNode *n; listIter *iter; sds str; //创建一个空的双端链表 list *l = listCreate(); //设置回调函数 listSetDupMethod(l, testDup); listSetFreeMethod(l, testFree); listSetMatchMethod(l, testMatch); //将数据加入到链表尾端 listAddNodeTail(l, sdsnewlen("Redis", 5)); listAddNodeTail(l, sdsnewlen("PHP", 3)); listAddNodeTail(l, sdsnewlen("MySQL", 5)); listAddNodeTail(l, sdsnewlen("Hadoop", 6)); listAddNodeTail(l, sdsnewlen("Strom", 5)); printf("adlist length:%d\n\n", listLength(l)); //查找名为Hadoop的节点 str = sdsnewlen("Hadoop", 6); n = listSearchKey(l, str); sdsfree(str); if (n != NULL) { printf("Search Result:%s\n\n", listNodeValue(n)); } else { printf("NO Result!!!\n\n"); } //遍历并输出所有数据 iter = listGetIterator(l, AL_START_HEAD); while ((n = listNext(iter))) { printf("Node Value: %s\n", listNodeValue(n)); } printf("\n"); //查找并删除索引为3的数据 n = listIndex(l, 3); if (n) { printf("Index 3 Is:%s\n\n", listNodeValue(n)); //删除索引为3的数据 listDelNode(l, n); printf("Index 3 is Removed, adlist length:%d\n\n", listLength(l)); } else { printf("Index 3 Is Not Exists!!!\n\n"); } //将新的节点加入到索引为1的后面 n = listIndex(l, 1); if (n) { listInsertNode(l, n, sdsnewlen("Python", 6), 1); //将新的节点加入到索引为1的前面 listInsertNode(l, n, sdsnewlen("Nginx", 5), 0); printf("Add Python before Index 1, Add Nginx After Index 1, adlist length:%d\n", listLength(l)); //遍历并输出所有数据 iter = listGetIterator(l, AL_START_HEAD); while ((n = listNext(iter))) { printf("Node Value: %s\n", listNodeValue(n)); } printf("\n"); } listRelease(l); return 1; } #endif