jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
3.6KB

  1. /* -*- Mode: C ; c-basic-offset: 2 -*- */
  2. /*****************************************************************************
  3. *
  4. * list_sort() adapted from linux kernel.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; version 2 of the License
  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. *****************************************************************************/
  20. #include <assert.h>
  21. #include "list.h"
  22. /* list sort from Mark J Roberts (mjr@znex.org) */
  23. void
  24. __list_sort (
  25. struct list_head *head,
  26. int member_offset,
  27. int (*cmp)(void * a, void * b))
  28. {
  29. struct list_head *p, *q, *e, *list, *tail, *oldhead;
  30. int insize, nmerges, psize, qsize, i;
  31. list = head->next;
  32. list_del (head);
  33. insize = 1;
  34. for (;; ) {
  35. p = oldhead = list;
  36. list = tail = NULL;
  37. nmerges = 0;
  38. while (p) {
  39. nmerges++;
  40. q = p;
  41. psize = 0;
  42. for (i = 0; i < insize; i++) {
  43. psize++;
  44. q = q->next == oldhead ? NULL : q->next;
  45. if (!q) {
  46. break;
  47. }
  48. }
  49. qsize = insize;
  50. while (psize > 0 || (qsize > 0 && q)) {
  51. if (!psize) {
  52. e = q;
  53. q = q->next;
  54. qsize--;
  55. if (q == oldhead) {
  56. q = NULL;
  57. }
  58. } else if (!qsize || !q) {
  59. e = p;
  60. p = p->next;
  61. psize--;
  62. if (p == oldhead) {
  63. p = NULL;
  64. }
  65. } else if (cmp ((void*)p - member_offset, (void*)q - member_offset) <= 0) {
  66. e = p;
  67. p = p->next;
  68. psize--;
  69. if (p == oldhead) {
  70. p = NULL;
  71. }
  72. } else {
  73. e = q;
  74. q = q->next;
  75. qsize--;
  76. if (q == oldhead) {
  77. q = NULL;
  78. }
  79. }
  80. if (tail) {
  81. tail->next = e;
  82. } else {
  83. list = e;
  84. }
  85. e->prev = tail;
  86. tail = e;
  87. }
  88. p = q;
  89. }
  90. tail->next = list;
  91. list->prev = tail;
  92. if (nmerges <= 1) {
  93. break;
  94. }
  95. insize *= 2;
  96. }
  97. head->next = list;
  98. head->prev = list->prev;
  99. list->prev->next = head;
  100. list->prev = head;
  101. }
  102. struct test_list_el {
  103. int value;
  104. struct list_head test_list_node;
  105. };
  106. int test_list_sort_comparator (struct test_list_el * e1, struct test_list_el * e2)
  107. {
  108. return e1->value - e2->value;
  109. }
  110. void test_list_sort (void)
  111. {
  112. struct list_head test_list;
  113. struct test_list_el *el, *next;
  114. struct test_list_el te1 = { .value = 1 };
  115. struct test_list_el te2 = { .value = 2 };
  116. struct test_list_el te3 = { .value = 3 };
  117. struct test_list_el te4 = { .value = 4 };
  118. struct test_list_el te5 = { .value = 5 };
  119. struct test_list_el te6 = { .value = 6 };
  120. struct test_list_el te7 = { .value = 7 };
  121. const int expected[] = { 1, 2, 3, 4, 5, 6, 7 };
  122. int i;
  123. INIT_LIST_HEAD (&test_list);
  124. list_add_tail (&te2.test_list_node, &test_list);
  125. list_add_tail (&te6.test_list_node, &test_list);
  126. list_add_tail (&te4.test_list_node, &test_list);
  127. list_add_tail (&te5.test_list_node, &test_list);
  128. list_add_tail (&te7.test_list_node, &test_list);
  129. list_add_tail (&te1.test_list_node, &test_list);
  130. list_add_tail (&te3.test_list_node, &test_list);
  131. list_sort (&test_list, struct test_list_el, test_list_node, test_list_sort_comparator);
  132. i = 0;
  133. list_for_each_entry_safe (el, next, &test_list, test_list_node) {
  134. assert (el->value == expected[i]);
  135. i++;
  136. }
  137. }