1 1.1 christos /* Manipulate doubly linked lists. 2 1.1 christos Copyright (C) 2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This program is free software; you can redistribute it and/or modify 5 1.1 christos it under the terms of the GNU General Public License as published by 6 1.1 christos the Free Software Foundation; either version 3 of the License, or 7 1.1 christos (at your option) any later version. 8 1.1 christos 9 1.1 christos This program is distributed in the hope that it will be useful, 10 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 11 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 1.1 christos GNU General Public License for more details. 13 1.1 christos 14 1.1 christos You should have received a copy of the GNU General Public License 15 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 1.1 christos 17 1.1 christos 18 1.1 christos #ifndef _DOUBLY_LINKED_LIST_H 19 1.1 christos #define _DOUBLY_LINKED_LIST_H 20 1.1 christos 21 1.1 christos /* Doubly linked list implementation enforcing typing. 22 1.1 christos 23 1.1 christos This implementation of doubly linked list tries to achieve the enforcement of 24 1.1 christos typing similarly to C++ templates, but without encapsulation. 25 1.1 christos 26 1.1 christos All the functions are prefixed with the type of the value: "AType_xxx". 27 1.1 christos Some functions are prefixed with "_AType_xxx" and are not part of the public 28 1.1 christos API, so should not be used, except for _##LTYPE##_merge_sort with a caveat 29 1.1 christos (see note above its definition). 30 1.1 christos 31 1.1 christos Each function (### is a placeholder for method name) has a macro for: 32 1.1 christos (1) its invocation LINKED_LIST_###(LTYPE). 33 1.1 christos (2) its prototype LINKED_LIST_DECL_###(A, A2, scope). To add in a header 34 1.1 christos file, or a source file for forward declaration. 'scope' should be set 35 1.1 christos respectively to 'extern', or 'static'. 36 1.1 christos (3) its definition LINKED_LIST_DEFN_###(A, A2, scope). To add in a source 37 1.1 christos file with the 'scope' set respectively to nothing, or 'static' depending 38 1.1 christos on (2). 39 1.1 christos 40 1.1 christos Data structures requirements: 41 1.1 christos - LTYPE corresponds to the node of a doubly linked list. It needs to define 42 1.1 christos attributes 'prev' and 'next' which are pointers on the type of a node. 43 1.1 christos For instance: 44 1.1 christos struct my_list_node 45 1.1 christos { 46 1.1 christos T value; 47 1.1 christos struct my_list_node *prev; 48 1.1 christos struct my_list_node *next; 49 1.1 christos }; 50 1.1 christos - LWRAPPERTYPE is a structure wrapping the nodes and others metadata (first, 51 1.1 christos last, size). 52 1.1 christos */ 53 1.1 christos 54 1.1 christos 55 1.1 christos /* Mutative operations: 57 1.1 christos - append 58 1.1 christos - prepend 59 1.1 christos - insert_before 60 1.1 christos - pop_front 61 1.1 christos - pop_back 62 1.1 christos - remove 63 1.1 christos - swap 64 1.1 christos The header and body of each of those operation can be declared individually, 65 1.1 christos or as a whole via LINKED_LIST_MUTATIVE_OPS_PROTOTYPE for the prototypes, and 66 1.1 christos LINKED_LIST_MUTATIVE_OPS_DECL for the implementations. */ 67 1.1 christos 68 1.1 christos /* Append the given node new_ to the exising list. 69 1.1 christos Precondition: prev and next of new_ must be NULL. */ 70 1.1 christos #define LINKED_LIST_APPEND(LTYPE) LTYPE##_append 71 1.1 christos 72 1.1 christos #define LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 73 1.1 christos EXPORT void \ 74 1.1 christos LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) 75 1.1 christos 76 1.1 christos #define LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 77 1.1 christos EXPORT void \ 78 1.1 christos LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) \ 79 1.1 christos { \ 80 1.1 christos if (wrapper->last == NULL) \ 81 1.1 christos wrapper->first = new_; \ 82 1.1 christos else \ 83 1.1 christos { \ 84 1.1 christos new_->prev = wrapper->last; \ 85 1.1 christos wrapper->last->next = new_; \ 86 1.1 christos } \ 87 1.1 christos wrapper->last = new_; \ 88 1.1 christos ++wrapper->size; \ 89 1.1 christos } 90 1.1 christos 91 1.1 christos /* Prepend the given node new_ to the existing list. 92 1.1 christos Precondition: prev and next of new_ must be NULL. */ 93 1.1 christos #define LINKED_LIST_PREPEND(LTYPE) LTYPE##_prepend 94 1.1 christos 95 1.1 christos #define LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 96 1.1 christos EXPORT void \ 97 1.1 christos LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) 98 1.1 christos 99 1.1 christos #define LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 100 1.1 christos EXPORT void \ 101 1.1 christos LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) \ 102 1.1 christos { \ 103 1.1 christos if (wrapper->first == NULL) \ 104 1.1 christos wrapper->last = new_; \ 105 1.1 christos else \ 106 1.1 christos { \ 107 1.1 christos new_->next = wrapper->first; \ 108 1.1 christos wrapper->first->prev = new_; \ 109 1.1 christos } \ 110 1.1 christos wrapper->first = new_; \ 111 1.1 christos ++wrapper->size; \ 112 1.1 christos } 113 1.1 christos 114 1.1 christos /* Insert the given node new_ before 'where' in the existing list. 115 1.1 christos If where == NULL, the insertion is equivalent to an append. 116 1.1 christos If where == first, the insertion is equivalent to a prepend. */ 117 1.1 christos #define LINKED_LIST_INSERT_BEFORE(LTYPE) LTYPE##_insert_before 118 1.1 christos 119 1.1 christos #define LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ 120 1.1 christos EXPORT void \ 121 1.1 christos LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ 122 1.1 christos LTYPE *new_, \ 123 1.1 christos LTYPE *where) 124 1.1 christos 125 1.1 christos #define LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ 126 1.1 christos EXPORT void \ 127 1.1 christos LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ 128 1.1 christos LTYPE *new_, \ 129 1.1 christos LTYPE *where) \ 130 1.1 christos { \ 131 1.1 christos if (where == wrapper->first) \ 132 1.1 christos LTYPE##_prepend (wrapper, new_); \ 133 1.1 christos else if (where == NULL) \ 134 1.1 christos LTYPE##_append (wrapper, new_); \ 135 1.1 christos else \ 136 1.1 christos { \ 137 1.1 christos where->prev->next = new_; \ 138 1.1 christos new_->prev = where->prev; \ 139 1.1 christos where->prev = new_; \ 140 1.1 christos new_->next = where; \ 141 1.1 christos ++wrapper->size; \ 142 1.1 christos } \ 143 1.1 christos } 144 1.1 christos 145 1.1 christos /* Pop the first node of the list. */ 146 1.1 christos #define LINKED_LIST_POP_FRONT(LTYPE) LTYPE##_pop_front 147 1.1 christos 148 1.1 christos #define LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ 149 1.1 christos EXPORT LTYPE * \ 150 1.1 christos LTYPE##_pop_front (LWRAPPERTYPE *wrapper) 151 1.1 christos 152 1.1 christos #define LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ 153 1.1 christos EXPORT LTYPE * \ 154 1.1 christos LTYPE##_pop_front (LWRAPPERTYPE *wrapper) \ 155 1.1 christos { \ 156 1.1 christos LTYPE *front_node = wrapper->first; \ 157 1.1 christos if (front_node != NULL) \ 158 1.1 christos { \ 159 1.1 christos wrapper->first = front_node->next; \ 160 1.1 christos if (wrapper->last == front_node) \ 161 1.1 christos wrapper->last = NULL; \ 162 1.1 christos else \ 163 1.1 christos { \ 164 1.1 christos front_node->next->prev = NULL; \ 165 1.1 christos front_node->next = NULL; \ 166 1.1 christos } \ 167 1.1 christos front_node->next = NULL; \ 168 1.1 christos --wrapper->size; \ 169 1.1 christos } \ 170 1.1 christos return front_node; \ 171 1.1 christos } 172 1.1 christos 173 1.1 christos /* Pop the last node of the list. */ 174 1.1 christos #define LINKED_LIST_POP_BACK(LTYPE) LTYPE##_pop_back 175 1.1 christos 176 1.1 christos #define LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ 177 1.1 christos EXPORT LTYPE * \ 178 1.1 christos LTYPE##_pop_back (LWRAPPERTYPE *wrapper) 179 1.1 christos 180 1.1 christos #define LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ 181 1.1 christos EXPORT LTYPE * \ 182 1.1 christos LTYPE##_pop_back (LWRAPPERTYPE *wrapper) \ 183 1.1 christos { \ 184 1.1 christos LTYPE *back_node = wrapper->last; \ 185 1.1 christos if (back_node != NULL) \ 186 1.1 christos { \ 187 1.1 christos wrapper->last = back_node->prev; \ 188 1.1 christos if (wrapper->first == back_node) \ 189 1.1 christos wrapper->first = NULL; \ 190 1.1 christos else \ 191 1.1 christos { \ 192 1.1 christos back_node->prev->next = NULL; \ 193 1.1 christos back_node->prev = NULL; \ 194 1.1 christos } \ 195 1.1 christos back_node->prev = NULL; \ 196 1.1 christos --wrapper->size; \ 197 1.1 christos } \ 198 1.1 christos return back_node; \ 199 1.1 christos } 200 1.1 christos 201 1.1 christos /* Remove the given node from the existing list, and return the previous 202 1.1 christos node. */ 203 1.1 christos #define LINKED_LIST_REMOVE(LTYPE) LTYPE##_remove 204 1.1 christos 205 1.1 christos #define LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ 206 1.1 christos EXPORT LTYPE * \ 207 1.1 christos LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) 208 1.1 christos 209 1.1 christos #define LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ 210 1.1 christos EXPORT LTYPE * \ 211 1.1 christos LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) \ 212 1.1 christos { \ 213 1.1 christos LTYPE *previous = NULL; \ 214 1.1 christos \ 215 1.1 christos if (node->prev != NULL) \ 216 1.1 christos { \ 217 1.1 christos node->prev->next = node->next; \ 218 1.1 christos if (node->next == NULL) \ 219 1.1 christos wrapper->last = node->prev; \ 220 1.1 christos else \ 221 1.1 christos node->next->prev = node->prev; \ 222 1.1 christos previous = node->prev; \ 223 1.1 christos node->next = NULL; \ 224 1.1 christos node->prev = NULL; \ 225 1.1 christos --wrapper->size; \ 226 1.1 christos } \ 227 1.1 christos else \ 228 1.1 christos LTYPE##_pop_front (wrapper); \ 229 1.1 christos \ 230 1.1 christos return previous; \ 231 1.1 christos } 232 1.1 christos 233 1.1 christos /* Generic swap. */ 234 1.1 christos #define LINKED_LIST_SWAP(LTYPE) LTYPE##_swap 235 1.1 christos 236 1.1 christos #define LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ 237 1.1 christos EXPORT void \ 238 1.1 christos LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) 239 1.1 christos 240 1.1 christos /* Swap two nodes in a list. */ 241 1.1 christos #define LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ 242 1.1 christos EXPORT void \ 243 1.1 christos LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) \ 244 1.1 christos { \ 245 1.1 christos LTYPE *prev1 = node1->prev; \ 246 1.1 christos LTYPE *next1 = node1->next; \ 247 1.1 christos LTYPE *prev2 = node2->prev; \ 248 1.1 christos LTYPE *next2 = node2->next; \ 249 1.1 christos \ 250 1.1 christos if (prev1 != NULL) \ 251 1.1 christos prev1->next = node2; \ 252 1.1 christos else \ 253 1.1 christos wrapper->first = node2; \ 254 1.1 christos if (prev2 != NULL) \ 255 1.1 christos prev2->next = node1; \ 256 1.1 christos else \ 257 1.1 christos wrapper->first = node1; \ 258 1.1 christos \ 259 1.1 christos if (next1 != NULL) \ 260 1.1 christos next1->prev = node2; \ 261 1.1 christos else \ 262 1.1 christos wrapper->last = node2; \ 263 1.1 christos if (next2 != NULL) \ 264 1.1 christos next2->prev = node1; \ 265 1.1 christos else \ 266 1.1 christos wrapper->last = node1; \ 267 1.1 christos \ 268 1.1 christos { \ 269 1.1 christos LTYPE *temp = node1->next; \ 270 1.1 christos node1->next = node2->next; \ 271 1.1 christos node2->next = temp; \ 272 1.1 christos } \ 273 1.1 christos { \ 274 1.1 christos LTYPE *temp = node1->prev; \ 275 1.1 christos node1->prev = node2->prev; \ 276 1.1 christos node2->prev = temp; \ 277 1.1 christos } \ 278 1.1 christos } 279 1.1 christos 280 1.1 christos /* Note: all the mutative operations below also update the data in the wrapper, 281 1.1 christos i.e. first, last and size. */ 282 1.1 christos #define LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ 283 1.1 christos LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ 284 1.1 christos LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ 285 1.1 christos LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT); \ 286 1.1 christos LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT); \ 287 1.1 christos LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT); \ 288 1.1 christos LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT); \ 289 1.1 christos LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) 290 1.1 christos 291 1.1 christos #define LINKED_LIST_MUTATIVE_OPS_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ 292 1.1 christos LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 293 1.1 christos LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ 294 1.1 christos LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ 295 1.1 christos LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ 296 1.1 christos LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ 297 1.1 christos LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ 298 1.1 christos LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) 299 1.1 christos 300 1.1 christos 301 1.1 christos /* Sorting. */ 303 1.1 christos 304 1.1 christos #define LINKED_LIST_MERGE_SORT_(LTYPE) LTYPE##_merge_sort_ 305 1.1 christos 306 1.1 christos #define LINKED_LIST_MERGE_SORT(LTYPE) LTYPE##_merge_sort 307 1.1 christos 308 1.1 christos #define LINKED_LIST_MERGE_SORT_PROTOTYPE_(LTYPE, EXPORT) \ 309 1.1 christos EXPORT LTYPE * \ 310 1.1 christos LTYPE##_merge_sort_ (LTYPE *node, \ 311 1.1 christos int (*fn_cmp) (const LTYPE *, const LTYPE *)) 312 1.1 christos 313 1.1 christos #define LINKED_LIST_MERGE_SORT_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ 314 1.1 christos EXPORT void \ 315 1.1 christos LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ 316 1.1 christos int (*fn_cmp) (const LTYPE *, const LTYPE *)) 317 1.1 christos 318 1.1 christos /* Note: all the functions and macros below starting with "_" should be 319 1.1 christos considered private. */ 320 1.1 christos 321 1.1 christos /* Compute the middle element of the list based on the turtle and hare 322 1.1 christos approach, i.e. the hare runs twice faster than the turtle. */ 323 1.1 christos #define _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ 324 1.1 christos static inline LTYPE * \ 325 1.1 christos LTYPE##_merge_sort_compute_turtle_ (LTYPE *node) \ 326 1.1 christos { \ 327 1.1 christos if (node == NULL) \ 328 1.1 christos return node; \ 329 1.1 christos \ 330 1.1 christos LTYPE *turtle = node, *hare = node->next; \ 331 1.1 christos while (hare != NULL && hare->next != NULL) \ 332 1.1 christos { \ 333 1.1 christos turtle = turtle->next; \ 334 1.1 christos hare = hare->next->next; \ 335 1.1 christos } \ 336 1.1 christos return turtle; \ 337 1.1 christos } 338 1.1 christos 339 1.1 christos /* Append n at the end of l_out, and return the next node after n. 340 1.1 christos l_out and l_last should be ideally encapsulated into a list structure 341 1.1 christos but this is overkill for what we need here. */ 342 1.1 christos #define _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ 343 1.1 christos static inline LTYPE * \ 344 1.1 christos LTYPE##_merge_sort_out_append_ (LTYPE **l_out, LTYPE **l_last, \ 345 1.1 christos LTYPE *n) \ 346 1.1 christos { \ 347 1.1 christos if (*l_last == NULL) \ 348 1.1 christos { \ 349 1.1 christos *l_last = n; \ 350 1.1 christos *l_out = n; \ 351 1.1 christos n->prev = NULL; \ 352 1.1 christos } \ 353 1.1 christos else \ 354 1.1 christos { \ 355 1.1 christos (*l_last)->next = n; \ 356 1.1 christos n->prev = *l_last; \ 357 1.1 christos *l_last = n; \ 358 1.1 christos } \ 359 1.1 christos \ 360 1.1 christos return n->next; \ 361 1.1 christos } 362 1.1 christos 363 1.1 christos /* Merge two sorted lists together. 364 1.1 christos The returned value corresponds to the first element of the list. 365 1.1 christos Note: both input lists are invalidated after the call. */ 366 1.1 christos #define _MERGE_SORT_IMPL_MERGE(LTYPE) \ 367 1.1 christos static inline LTYPE * \ 368 1.1 christos LTYPE##_merge_sort_merge_ (LTYPE *l_left, LTYPE *l_right, \ 369 1.1 christos int (*fn_cmp) (const LTYPE *, const LTYPE *))\ 370 1.1 christos { \ 371 1.1 christos if (l_left == NULL) \ 372 1.1 christos return l_right; \ 373 1.1 christos else if (l_right == NULL) \ 374 1.1 christos return l_left; \ 375 1.1 christos \ 376 1.1 christos LTYPE *l_out = NULL, *l_last = NULL; \ 377 1.1 christos \ 378 1.1 christos LTYPE *l_l = l_left, *l_r = l_right; \ 379 1.1 christos while (l_l != NULL && l_r != NULL) \ 380 1.1 christos { \ 381 1.1 christos int cmp = fn_cmp (l_l, l_r); \ 382 1.1 christos if (cmp <= 0) \ 383 1.1 christos l_l = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_l); \ 384 1.1 christos else \ 385 1.1 christos l_r = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_r); \ 386 1.1 christos } \ 387 1.1 christos \ 388 1.1 christos LTYPE *l_remaining = (l_l != NULL) ? l_l : l_r; \ 389 1.1 christos while (l_remaining != NULL) \ 390 1.1 christos l_remaining = \ 391 1.1 christos LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_remaining); \ 392 1.1 christos \ 393 1.1 christos return l_out; \ 394 1.1 christos } 395 1.1 christos 396 1.1 christos /* Merge sort implementation taking the first node of the list to sort, 397 1.1 christos and the comparison function. Returns the first node of the sorted list. 398 1.1 christos Note: use this if you don't care about updating the information in the 399 1.1 christos wrapper. */ 400 1.1 christos #define _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ 401 1.1 christos EXPORT LTYPE * \ 402 1.1 christos LTYPE##_merge_sort_ (LTYPE *node, \ 403 1.1 christos int (*fn_cmp)(const LTYPE *, const LTYPE *)) \ 404 1.1 christos { \ 405 1.1 christos if (node == NULL) \ 406 1.1 christos return NULL; \ 407 1.1 christos else if (node->next == NULL) \ 408 1.1 christos return node; \ 409 1.1 christos \ 410 1.1 christos LTYPE *left_end = LTYPE##_merge_sort_compute_turtle_ (node); \ 411 1.1 christos LTYPE *left_begin = node; \ 412 1.1 christos LTYPE *right_begin = left_end->next; \ 413 1.1 christos /* break the list. */ \ 414 1.1 christos left_end->next = NULL; \ 415 1.1 christos right_begin->prev = NULL; \ 416 1.1 christos \ 417 1.1 christos left_begin = LTYPE##_merge_sort_ (left_begin, fn_cmp); \ 418 1.1 christos right_begin = LTYPE##_merge_sort_ (right_begin, fn_cmp); \ 419 1.1 christos return LTYPE##_merge_sort_merge_ (left_begin, right_begin, fn_cmp); \ 420 1.1 christos } 421 1.1 christos 422 1.1 christos /* Merge sort wrapper that the end-user should be using as it updates the 423 1.1 christos first and last metadata of the list in wrapper as well. 424 1.1 christos If the user does not want to pay the cost of the update of the data, 425 1.1 christos it can directly use _##LTYPE##_merge_sort_merge. */ 426 1.1 christos #define _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) \ 427 1.1 christos EXPORT void \ 428 1.1 christos LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ 429 1.1 christos int (*fn_cmp) (const LTYPE *, const LTYPE *)) \ 430 1.1 christos { \ 431 1.1 christos wrapper->first = LTYPE##_merge_sort_ (wrapper->first, fn_cmp); \ 432 1.1 christos \ 433 1.1 christos if (wrapper->first == NULL || wrapper->first->next == NULL) \ 434 1.1 christos wrapper->last = wrapper->first; \ 435 1.1 christos else \ 436 1.1 christos for (LTYPE *node = wrapper->first; \ 437 1.1 christos node != NULL; \ 438 1.1 christos node = node->next) \ 439 1.1 christos wrapper->last = node; \ 440 1.1 christos } 441 1.1 christos 442 1.1 christos #define LINKED_LIST_MERGE_SORT_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ 443 1.1 christos _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ 444 1.1 christos _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ 445 1.1 christos _MERGE_SORT_IMPL_MERGE(LTYPE) \ 446 1.1 christos _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ 447 1.1 christos _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) 448 449 #endif /* _DOUBLY_LINKED_LIST_H */ 450