沉淀之log4c的list

    log4c中对于链表也实现了一套,可以在src/sd/目录下找到有对应的list.c和list.h两个文件。直接贴代码和注释。
list.h
  1. #ifndef __sd_list_h
  2. #define __sd_list_h

  3. #include <stddef.h>
  4. #include "defs.h"
  5. __SD_BEGIN_DECLS
  6. /**
  7. * 声明list类型,实际定义是在list.c文件里
  8. */
  9. typedef struct __sd_list sd_list_t;
  10. /**
  11. * 定义list中元素的结构,data应该是指向用户数据的指针,
  12. * 双向链表
  13. */
  14. struct __sd_list_iter {
  15. void* data;
  16. struct __sd_list* list;
  17. struct __sd_list_iter* __next;
  18. struct __sd_list_iter* __prev;
  19. int __foreach;
  20. };
  21. /**
  22. * 对于元素容器进行类型的定义
  23. */
  24. typedef struct __sd_list_iter sd_list_iter_t;
  25. /**
  26. * foreach遍历时的回调函数类型
  27. */
  28. typedef unsigned int (*sd_list_func_t)(void* a_data, void* a_userdata);
  29. /**
  30. * 新建一个链表
  31. * @param a_capacity 初始化链表中容纳元素的数量
  32. * @return 链表的入口指针.
  33. */
  34. extern sd_list_t* sd_list_new(size_t a_capacity);
  35. /**
  36. * 销毁一个链表
  37. * @todo 需要一个回调函数来释放用户数据(尚未实现)
  38. */
  39. extern void sd_list_delete(sd_list_t* a_this);
  40. /**
  41. * 将用户数据插入到链表的头部
  42. */
  43. extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data);
  44. /**
  45. * 将用户数据插入到链表的尾部
  46. */
  47. extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data);
  48. /**
  49. * 在链表里查找用户数据是否存在
  50. * @param a_data 待查找数据
  51. * @return 找到的元素地址,或者NULL.
  52. */
  53. extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data);
  54. /**
  55. * 在链表里查找数据,如果没有找到就调用sd_list_add().将数据插入到链表里
  56. * @param a_data 待查找数据
  57. * @return 查找到的数据地址,或者NULL.
  58. */
  59. extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data);
  60. /**
  61. * 将用户数据插入到链表里,如果该数据已经存在则返回数据的指针
  62. * @warning 元素会插入到链表的头部
  63. * @param a_data 带插入数据
  64. * @return 返回插入的或者已存在的元素指针
  65. */
  66. extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data);
  67. /**
  68. * 用a_func从头遍历链表中的所有元素,直到返回一个非NULL的返回值,则
  69. * 将用户数据插入到返回的数据前面
  70. * @param a_func 排序函数
  71. * @param a_data 待插入的用户数据
  72. * @return 用户数据插入后所在的容器指针
  73. */
  74. extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
  75. sd_list_func_t a_func,
  76. void* a_data);
  77. /**
  78. * 从链表里删除一个用户数据
  79. * @param a_data 包含用户数据的容器地址
  80. */
  81. extern int sd_list_del(sd_list_t* a_this, void* a_data);
  82. /**
  83. * 清空一个链表
  84. */
  85. extern void sd_list_clear(sd_list_t* a_this);
  86. /**
  87. * 调用a_func从头遍历整个链表直到返回一个非0
  88. * @param a_func 遍历回调函数
  89. * @param a_data 传入到回调函数的一个用户数据
  90. */
  91. extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
  92. void* a_userdata);
  93. /**
  94. * 调用a_func从后向前遍历整个链表直到返回一个非0
  95. * @param a_func 遍历回调函数
  96. * @param a_data 传入到回调函数的用户数据
  97. */
  98. extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
  99. void* a_userdata);
  100. /**
  101. * 获取链表中元素的个数
  102. */
  103. extern size_t sd_list_get_nelem(sd_list_t* a_this);
  104. /**
  105. * 获取链表中第一个容器
  106. */
  107. extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
  108. /**
  109. * Gets the past-the-last-element iterator of the list.
  110. * 函数定义未实现
  111. */
  112. extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
  113. /**
  114. * 获取链表中最后一个元素
  115. */
  116. extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
  117. /**
  118. * Gets the before-the-first-element iterator of the list.
  119. * 函数定义未实现
  120. */
  121. extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
  122. /**
  123. * 得到当前容器的下一个容器
  124. */
  125. extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this);
  126. /**
  127. * 得到当前容器的前一个容器
  128. */
  129. extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this);
  130. /**
  131. * 从链表中删除一个容器
  132. */
  133. extern void sd_list_iter_del(sd_list_iter_t* a_this);
  134. /**
  135. * 创建一个新的容器并将数据插入到a_this前面
  136. * @param a_data 放入到新建容器的数据
  137. */
  138. extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
  139. void* a_data);
  140. __SD_END_DECLS
  141. #endif

list.h中声明的函数,是在list.c中进行了实现,其中声明的两个函数:
extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
功能与
extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
重复,所以在list.c里面只进行定义了一个空的函数体,并没有进行实现。

以下是list.c中的内容:
  1. #include "list.h"
  2. #include "malloc.h"
  3. #include <stdlib.h>
  4. struct __sd_list {
  5. sd_list_iter_t* head;
  6. sd_list_iter_t* tail;
  7. size_t nelem;
  8. };
    list.h中有一个typedef语句:typedef struct __sd_list sd_list_t;    将sd_list_t声明一下然后在这里进行实际的结构体的定义,这样下面的函数声明中就可以使用这个sd_list_t进行参数或者返回值的声明了。并且只要引用了list.h就可以使用sd_list_t来进行定义自己的链表句柄。这样可以比较完美的实现结构体的隐藏同时还能比较容易使用。
    从这里就知道了整个链表的结构是什么样的了。具体的可以参考图一:

图一:链表的整体结构图
sd_list_new:
  1. extern sd_list_t* sd_list_new(size_t a_capacity)
  2. {
  3. sd_list_t* this;
  4. //申请内存,并初始化。实际上calloc分配的就是初始化了的内存。
  5. this = sd_calloc(1, sizeof(sd_list_t));
  6. this->head = 0;
  7. this->tail = 0;
  8. this->nelem = 0;
  9. return this;
  10. }
sd_list_prepend:
  1. extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data)
  2. {
  3. //定义一个容器,参数有效性判断。并进行容器内存分配和检查
  4. sd_list_iter_t* i;
  5. if (! a_this) return 0;
  6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
  7. return 0;
  8. //填充容器,用户数据,链表等。
  9. i->list = a_this;
  10. i->data = a_data;
  11. i->__prev = 0;
  12. i->__next = a_this->head;
  13. a_this->head = i;
  14. //接通后面的链表,否则设置链表的tail指针的指向
  15. if (i->__next)
  16. i->__next->__prev = i;
  17. else
  18. a_this->tail = i;
  19. //增加元素计数器
  20. a_this->nelem++;
  21. return i;
  22. }

sd_list_append:
  1. extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data)
  2. {
  3. sd_list_iter_t* i;
  4. if (! a_this) return 0;
  5. //定义一个容器,参数有效性判断。并进行容器内存分配和检查
  6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
  7. return 0;
  8. //填充容器,用户数据,链表等。
  9. i->list = a_this;
  10. i->data = a_data;
  11. i->__prev = a_this->tail;
  12. i->__next = 0;
  13. a_this->tail = i;
  14. //链接前面的链表或者设置链表的head指针
  15. if (i->__prev)
  16. i->__prev->__next = i;
  17. else
  18. a_this->head = i;
  19. //计数器加一
  20. a_this->nelem++;
  21. return i;
  22. }

sd_list_delete:
  1. extern void sd_list_delete(sd_list_t* a_this)
  2. {
  3. sd_list_iter_t *a_next;
  4. sd_list_iter_t *a_current;
  5. if (!a_this)
  6. return;
  7. //释放所有的容器
  8. /* Free the iterators */
  9. if (a_this->nelem > 0){
  10. a_current = a_this->head;
  11. do {
  12. a_next = a_current->__next;
  13. free(a_current);
  14. a_current = a_next;
  15. } while (a_current);
  16. }
  17. //释放链表 句柄
  18. free(a_this);
  19. }

sd_list_clear:
  1. extern void sd_list_clear(sd_list_t* a_this)
  2. {
  3. a_this->head = 0;
  4. a_this->tail = 0;
  5. a_this->nelem = 0;
  6. }

sd_list_get_nelem:
  1. extern size_t sd_list_get_nelem(sd_list_t* a_this)
  2. {
  3. return (a_this ? a_this->nelem : 0);
  4. }

sd_list_begin:
  1. extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this)
  2. {
  3. return (a_this ? a_this->head : 0);
  4. }

sd_list_rbegin:
  1. extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this)
  2. {
  3. return (a_this ? a_this->tail : 0);
  4. }

sd_list_lookup:
  1. extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data)
  2. {
  3. sd_list_iter_t* i;
  4. if (! a_this) return 0;
  5. //遍历直到找到数据地址与用户传入的地址相同,返回容器地址
  6. for (i = a_this->head; i; i = i->__next)
  7. if (a_data == i->data)
  8. return i;
  9. return 0;
  10. }

sd_list_add:
  1. extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data)
  2. {
  3. sd_list_iter_t* i;
  4. if (! a_this) return 0;
  5. //新建一个容器并分配内存检查
  6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
  7. return 0;
  8. //填充
  9. i->data = a_data;
  10. i->list = a_this;
  11. i->__next = a_this->head;
  12. i->__prev = 0;
  13. a_this->head = i;
  14. //插入首部
  15. if (i->__next) i->__next->__prev = i;
  16. if (!a_this->tail) a_this->tail = i;
  17. //计数器加一
  18. a_this->nelem++;
  19. return i;
  20. }

sd_list_lookadd:
  1. extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data)
  2. {
  3. sd_list_iter_t* i;
  4. if (! a_this) return 0;
  5. //调用sd_list_lookup,或者就插入并返回
  6. if ((i = sd_list_lookup(a_this, a_data)) != 0)
  7. return i;
  8. return sd_list_add(a_this, a_data);
  9. }

sd_list_iter_insert:
  1. extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
  2. void* a_data)
  3. {
  4. sd_list_iter_t* i;
  5. if (! a_this) return 0;
  6. //如果錫_this就是头节点那么就头插
  7. if (a_this->list->head == a_this)
  8. return sd_list_prepend(a_this->list, a_data);
  9. //申请内存,填充后插入到a_this之前
  10. if ((i = sd_calloc(1, sizeof(*i))) == 0)
  11. return 0;
  12. i->data = a_data;
  13. i->list = a_this->list;
  14. i->__prev = a_this->__prev;
  15. i->__next = a_this;
  16. /* CAUTION: always exists since a_this is not the head */
  17. a_this->__prev->__next = i;
  18. a_this->__prev = i;
  19. //计数器加一
  20. a_this->list->nelem++;
  21. return i;
  22. }

sd_list_sortadd:
  1. extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
  2. sd_list_func_t a_func, void* a_data)
  3. {
  4. sd_list_iter_t* i;
  5. //参数检查
  6. if (! a_this || ! a_func) return 0;
  7. //从头遍历直到找到一个大于当前用户数据的位置
  8. for (i = a_this->head; i; i = i->__next)
  9. if ((*a_func)(i->data, a_data) > 0)
  10. break;
  11. //如果不是最后的位置,那么插入新节点到a_data之前。否则添加在最后
  12. if (i)
  13. return sd_list_iter_insert(i, a_data);
  14. else
  15. return sd_list_append(a_this, a_data);
  16. }

sd_list_iter_del:
  1. extern void sd_list_iter_del(sd_list_iter_t* a_this)
  2. {
  3. if (!a_this)
  4. return;
  5. if (a_this->__foreach == 1) {
  6. a_this->__foreach = 0;
  7. return;
  8. }
  9. //向后接通
  10. if (a_this->__next)
  11. a_this->__next->__prev = a_this->__prev;
  12. else
  13. a_this->list->tail = a_this->__prev;
  14. //向前接通
  15. if (a_this->__prev)
  16. a_this->__prev->__next = a_this->__next;
  17. else
  18. a_this->list->head = a_this->__next;
  19. //计数器减一
  20. a_this->list->nelem--;
  21. //释放当前数据
  22. free(a_this);
  23. }

sd_list_del:
  1. extern int sd_list_del(sd_list_t* a_this, void* a_data)
  2. {
  3. sd_list_iter_t* i;
  4. if (!a_this)
  5. return -1;
  6. //遍历直到找到这个数据
  7. for (i = a_this->head; i; i = i->__next)
  8. if (a_data == i->data)
  9. break;
  10. //如果没找到
  11. if (!i)
  12. return -1;
  13. //删除这个元素
  14. sd_list_iter_del(i);
  15. return 0;
  16. }

sd_list_foreach:
  1. extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
  2. void* a_userdata)
  3. {
  4. sd_list_iter_t* i;
  5. sd_list_iter_t* j;
  6. if (!a_this || !a_func)
  7. return;
  8. //从头到尾遍历整个链表
  9. for (i = a_this->head; i; i = j)
  10. {
  11. int ret;
  12. i->__foreach = 1;
  13. ret = (*a_func)(i->data, a_userdata);
  14. j = i->__next;
  15. if (i->__foreach == 0)
  16. sd_list_iter_del(i);
  17. else
  18. i->__foreach = 0;
  19. if (ret) return;
  20. }
  21. }

sd_list_rforeach:
  1. extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
  2. void* a_userdata)
  3. {
  4. sd_list_iter_t* i;
  5. sd_list_iter_t* j;
  6. if (!a_this || !a_func)
  7. return;
  8. for (i = a_this->tail; i; i = j) {
  9. int ret;
  10. i->__foreach = 1;
  11. ret = (*a_func)(i->data, a_userdata);
  12. j = i->__prev;
  13. if (i->__foreach == 0)
  14. sd_list_iter_del(i);
  15. else
  16. i->__foreach = 0;
  17. if (ret) return;
  18. }
  19. }

sd_list_iter_next:
  1. extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this)
  2. {
  3. return (a_this ? a_this->__next : 0);
  4. }

sd_list_iter_prev:
  1. extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this)
  2. {
  3. return (a_this ? a_this->__prev : 0);
  4. }
   
    一个简单的样例测试程序如下:
main.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "stack.h"
  4. #include "list.h"
  5. typedef struct test
  6. {
  7. int a;
  8. int b;
  9. int c;
  10. }test_t;
  11. static unsigned int print(void *data, void *p)
  12. {
  13. test_t *t = (test_t *)data;
  14. printf("a:%d b:%d c:%d ",t->a, t->b, t->c);
  15. return 0;
  16. }
  17. int main()
  18. {
  19. sd_list_t* a_this = sd_list_new(24);
  20. test_t *t3 = malloc(sizeof(test_t));
  21. t3->a = 3;
  22. t3->b = 4;
  23. t3->c = 5;
  24. sd_list_prepend(a_this, t3);
  25. test_t *t1 = malloc(sizeof(test_t));
  26. t1->a = 1;
  27. t1->b = 2;
  28. t1->c = 3;
  29. sd_list_prepend(a_this, t1);
  30. test_t *t2 = malloc(sizeof(test_t));
  31. t2->a = 2;
  32. t2->b = 3;
  33. t2->c = 4;
  34. sd_list_prepend(a_this, t2);
  35. sd_list_foreach(a_this, print, NULL);
  36. printf("remains in list:%d ", sd_list_get_nelem(a_this));
  37. sd_list_delete(a_this);
  38. return 0;
  39. }







原文地址:https://www.cnblogs.com/cfzhang/p/8c343c0bb8715ee6317b49f7aa62ebd4.html