Home | History | Annotate | Line # | Download | only in include
      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