list_i.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /* Internal */
  20. PJ_INLINE(void) pj_link_node(pj_list_type *prev, pj_list_type *next)
  21. {
  22. ((pj_list*)prev)->next = next;
  23. ((pj_list*)next)->prev = prev;
  24. }
  25. PJ_IDEF(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node)
  26. {
  27. ((pj_list*)node)->prev = pos;
  28. ((pj_list*)node)->next = ((pj_list*)pos)->next;
  29. ((pj_list*) ((pj_list*)pos)->next) ->prev = node;
  30. ((pj_list*)pos)->next = node;
  31. }
  32. PJ_IDEF(void) pj_list_insert_before(pj_list_type *pos, pj_list_type *node)
  33. {
  34. pj_list_insert_after(((pj_list*)pos)->prev, node);
  35. }
  36. PJ_IDEF(void) pj_list_insert_nodes_after(pj_list_type *pos, pj_list_type *lst)
  37. {
  38. pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;
  39. pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;
  40. pj_link_node(pos, lst);
  41. pj_link_node(lst_last, pos_next);
  42. }
  43. PJ_IDEF(void) pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst)
  44. {
  45. pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst);
  46. }
  47. PJ_IDEF(void) pj_list_insert_list_after(pj_list_type *pos, pj_list_type *lst)
  48. {
  49. if (!pj_list_empty(lst)) {
  50. pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;
  51. pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;
  52. pj_link_node(pos, (pj_list *) ((pj_list*)lst)->next);
  53. pj_link_node(lst_last, pos_next);
  54. pj_list_init(lst);
  55. }
  56. }
  57. PJ_IDEF(void) pj_list_insert_list_before(pj_list_type *pos, pj_list_type *lst)
  58. {
  59. pj_list_insert_list_after(((pj_list*)pos)->prev, lst);
  60. }
  61. PJ_IDEF(void) pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2)
  62. {
  63. if (!pj_list_empty(lst2)) {
  64. pj_link_node(((pj_list*)lst1)->prev, ((pj_list*)lst2)->next);
  65. pj_link_node(((pj_list*)lst2)->prev, lst1);
  66. pj_list_init(lst2);
  67. }
  68. }
  69. PJ_IDEF(void) pj_list_merge_first(pj_list_type *lst1, pj_list_type *lst2)
  70. {
  71. if (!pj_list_empty(lst2)) {
  72. pj_link_node(((pj_list*)lst2)->prev, ((pj_list*)lst1)->next);
  73. pj_link_node(((pj_list*)lst1), ((pj_list*)lst2)->next);
  74. pj_list_init(lst2);
  75. }
  76. }
  77. PJ_IDEF(void) pj_list_erase(pj_list_type *node)
  78. {
  79. pj_link_node( ((pj_list*)node)->prev, ((pj_list*)node)->next);
  80. /* It'll be safer to init the next/prev fields to itself, to
  81. * prevent multiple erase() from corrupting the list. See
  82. * ticket #520 for one sample bug.
  83. */
  84. pj_list_init(node);
  85. }
  86. PJ_IDEF(pj_list_type*) pj_list_find_node(pj_list_type *list, pj_list_type *node)
  87. {
  88. pj_list *p = (pj_list *) ((pj_list*)list)->next;
  89. while (p != list && p != node)
  90. p = (pj_list *) p->next;
  91. return p==node ? p : NULL;
  92. }
  93. PJ_IDEF(pj_list_type*) pj_list_search(pj_list_type *list, void *value,
  94. int (*comp)(void *value, const pj_list_type *node))
  95. {
  96. pj_list *p = (pj_list *) ((pj_list*)list)->next;
  97. while (p != list && (*comp)(value, p) != 0)
  98. p = (pj_list *) p->next;
  99. return p==list ? NULL : p;
  100. }
  101. PJ_IDEF(pj_size_t) pj_list_size(const pj_list_type *list)
  102. {
  103. const pj_list *node = (const pj_list*) ((const pj_list*)list)->next;
  104. pj_size_t count = 0;
  105. while (node != list) {
  106. ++count;
  107. node = (pj_list*)node->next;
  108. }
  109. return count;
  110. }