src/linked_list.c

Tue, 05 Oct 2021 11:19:32 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 05 Oct 2021 11:19:32 +0200
changeset 460
e075009b33b7
parent 457
8f7d3fe9ca40
child 466
28bc3e10ac28
permissions
-rw-r--r--

remove convenience macros

Users should write their own wrappers s.t. the type
information does not have to be repeated on every
call site.

398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1 /*
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
3 *
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
5 *
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
8 *
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
11 *
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
15 *
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
27 */
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
28
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
29 #include "cx/linked_list.h"
401
e6a8f7fb0c45 copy list items when they are added to the list
Mike Becker <universe@uap-core.de>
parents: 400
diff changeset
30 #include <stdint.h>
e6a8f7fb0c45 copy list items when they are added to the list
Mike Becker <universe@uap-core.de>
parents: 400
diff changeset
31 #include <string.h>
453
bb144d08cd44 add some documentation and changes some signatures
Mike Becker <universe@uap-core.de>
parents: 451
diff changeset
32 #include <assert.h>
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
33
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
34 /* LOW LEVEL LINKED LIST FUNCTIONS */
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
35
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
36 #define CX_LL_PTR(cur, off) ((void**)(((char*)cur)+off))
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
37
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
38 void *cx_linked_list_at(void *start, size_t start_index, ptrdiff_t loc_advance, size_t index) {
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
39 size_t i = start_index;
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
40 void *cur = start;
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
41 while (i != index && cur != NULL) {
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
42 cur = *CX_LL_PTR(cur, loc_advance);
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
43 i < index ? i++ : i--;
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
44 }
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
45 return cur;
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
46 }
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
47
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
48 void *cx_linked_list_last(void *begin, ptrdiff_t loc_next) {
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
49 if (begin == NULL)
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
50 return NULL;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
51
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
52 void *cur = begin;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
53 void *last;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
54 do {
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
55 last = cur;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
56 } while ((cur = *CX_LL_PTR(cur, loc_next)) != NULL);
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
57
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
58 return last;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
59 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
60
453
bb144d08cd44 add some documentation and changes some signatures
Mike Becker <universe@uap-core.de>
parents: 451
diff changeset
61 void cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) {
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
62 void *last;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
63 if (end == NULL) {
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
64 assert(begin != NULL);
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
65 last = cx_linked_list_last(*begin, loc_next);
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
66 } else {
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
67 last = *end;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
68 }
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
69 if (last == NULL) {
453
bb144d08cd44 add some documentation and changes some signatures
Mike Becker <universe@uap-core.de>
parents: 451
diff changeset
70 assert(begin != NULL);
bb144d08cd44 add some documentation and changes some signatures
Mike Becker <universe@uap-core.de>
parents: 451
diff changeset
71 *begin = new_node;
428
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
72 } else {
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
73 // if there is a last node, update its next pointer
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
74 void **next = CX_LL_PTR(last, loc_next);
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
75 *next = new_node;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
76 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
77
428
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
78 // if there is an end pointer, update it
408
dfdd571550f8 fixes cx_linked_list_add not recalculating end
Mike Becker <universe@uap-core.de>
parents: 407
diff changeset
79 if (end != NULL) {
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
80 *end = cx_linked_list_last(new_node, loc_next);
408
dfdd571550f8 fixes cx_linked_list_add not recalculating end
Mike Becker <universe@uap-core.de>
parents: 407
diff changeset
81 }
428
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
82
da66264af8ad fix special cases for linked_list_add
Mike Becker <universe@uap-core.de>
parents: 423
diff changeset
83 // if the nodes use a prev pointer, update it
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
84 if (loc_prev >= 0) {
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
85 void **prev = CX_LL_PTR(new_node, loc_prev);
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
86 *prev = last;
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
87 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
88 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
89
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
90 /* HIGH LEVEL LINKED LIST IMPLEMENTATION */
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
91
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
92 typedef struct cx_linked_list_node cx_linked_list_node;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
93 struct cx_linked_list_node {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
94 cx_linked_list_node *prev;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
95 cx_linked_list_node *next;
403
8fa43b732980 use C99 flexible array to mark the node's payload
Mike Becker <universe@uap-core.de>
parents: 402
diff changeset
96 char payload[];
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
97 };
402
a34b93911956 use named fields to access node memory
Mike Becker <universe@uap-core.de>
parents: 401
diff changeset
98
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
99 #define CX_LL_LOC_PREV offsetof(cx_linked_list_node, prev)
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
100 #define CX_LL_LOC_NEXT offsetof(cx_linked_list_node, next)
439
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
101
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
102 typedef struct {
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
103 cx_list_s base;
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
104 cx_linked_list_node *begin;
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
105 cx_linked_list_node *end;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
106 } cx_linked_list;
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
107
448
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
108 static cx_linked_list_node *cx_ll_node_at(cx_linked_list *list, size_t index) {
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
109 if (index >= list->base.size) {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
110 return NULL;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
111 } else if (index > list->base.size / 2) {
457
8f7d3fe9ca40 fix bad start index in cx_ll_node_at()
Mike Becker <universe@uap-core.de>
parents: 456
diff changeset
112 return cx_linked_list_at(list->end, list->base.size-1, CX_LL_LOC_PREV, index);
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
113 } else {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
114 return cx_linked_list_at(list->begin, 0, CX_LL_LOC_NEXT, index);
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
115 }
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
116 }
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
117
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
118 static int cx_ll_insert(cx_list_s *list, size_t index, void *elem) {
448
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
119 // out-of bounds check
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
120 if (index > list->size) return 1;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
121
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
122 // cast a linked list pointer
437
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
123 cx_linked_list *ll = (cx_linked_list *) list;
448
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
124
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
125 // create the new node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
126 cx_linked_list_node *node = cxMalloc(list->allocator,
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
127 sizeof(cx_linked_list_node) + list->itemsize);
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
128
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
129 // sortir if failed
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
130 if (node == NULL) return 1;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
131
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
132 // copy payload to the new node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
133 memcpy(node->payload, elem, list->itemsize);
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
134
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
135 // check if this is the first node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
136 if (ll->begin == NULL) {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
137 node->prev = node->next = NULL;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
138 ll->begin = ll->end = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
139 } else {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
140 // check if this shall be the new end node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
141 if (index == list->size) {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
142 ll->end->next = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
143 node->prev = ll->end;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
144 node->next = NULL;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
145 ll->end = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
146 }
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
147 // check if this shall be the new start node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
148 else if (index == 0) {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
149 ll->begin->prev = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
150 node->next = ll->begin;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
151 node->prev = NULL;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
152 ll->begin = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
153 } else {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
154 // find the node at the current index
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
155 cx_linked_list_node *cur = cx_ll_node_at(ll, index);
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
156
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
157 // insert before that node
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
158 // (we know all ptr are non-null because we handled all other cases before)
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
159 node->next = cur;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
160 node->prev = cur->prev;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
161 cur->prev = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
162 node->prev->next = node;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
163 }
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
164 }
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
165
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
166 // increase the size and return
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
167 list->size++;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
168 return 0;
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
169 }
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
170
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
171 static int cx_ll_add(cx_list_s *list, void *elem) {
37c5d2fdb36b implement cx_ll_insert()
Mike Becker <universe@uap-core.de>
parents: 447
diff changeset
172 return cx_ll_insert(list, list->size, elem);
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
173 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
174
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
175 static int cx_ll_remove(cx_list_s *list, size_t index) {
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
176 cx_linked_list *ll = (cx_linked_list *) list;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
177 cx_linked_list_node *node = cx_ll_node_at(ll, index);
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
178
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
179 // out-of-bounds check
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
180 if (node == NULL) return 1;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
181
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
182 // change left side connection
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
183 if (node->prev == NULL) {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
184 ll->begin = node->next;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
185 } else {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
186 node->prev->next = node->next;
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
187 }
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
188
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
189 // change right side connection
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
190 if (node->next == NULL) {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
191 ll->end = node->prev;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
192 } else {
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
193 node->next->prev = node->prev;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
194 }
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
195
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
196 // adjust size
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
197 list->size--;
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
198
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
199 // free and return
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
200 cxFree(list->allocator, node);
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
201
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
202 return 0;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
203 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
204
439
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
205 static void *cx_ll_at(cx_list_s *list, size_t index) {
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
206 cx_linked_list *ll = (cx_linked_list *) list;
447
87b2cdd668ed implement cx_ll_remove()
Mike Becker <universe@uap-core.de>
parents: 446
diff changeset
207 cx_linked_list_node *node = cx_ll_node_at(ll, index);
440
003aa0a78e1e fix mixed up cases in cx_ll_at()
Mike Becker <universe@uap-core.de>
parents: 439
diff changeset
208 return node == NULL ? NULL : &node->payload;
439
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
209 }
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
210
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
211 static size_t cx_ll_find(cx_list_s *list, void *elem) {
437
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
212 CxListComparator cmp = list->cmpfunc;
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
213 cx_linked_list *ll = (cx_linked_list *) list;
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
214
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
215 size_t index;
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
216 cx_linked_list_node *node = ll->begin;
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
217 for (index = 0; index < list->size; index++) {
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
218 void *current = node->payload;
437
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
219 if (cmp(current, elem) == 0) {
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
220 return index;
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
221 }
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
222 node = node->next;
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
223 }
9d4971ea0625 implement linked list find
Mike Becker <universe@uap-core.de>
parents: 436
diff changeset
224 return index;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
225 }
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
226
438
cd3069757010 add function cx_linked_list_at()
Mike Becker <universe@uap-core.de>
parents: 437
diff changeset
227 static void *cx_ll_last(cx_list_s *list) {
439
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
228 cx_linked_list *ll = (cx_linked_list *) list;
456
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
229 cx_linked_list_node *last = ll->end;
227c2eabbef8 change cx_linked_list_last() and add a test for it
Mike Becker <universe@uap-core.de>
parents: 453
diff changeset
230 return last == NULL ? NULL : &last->payload;
404
86ebc3745e62 adds cxListLast
Mike Becker <universe@uap-core.de>
parents: 403
diff changeset
231 }
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
232
451
db06dda7ac4d make cx_linked_list_class static
Mike Becker <universe@uap-core.de>
parents: 448
diff changeset
233 static cx_list_class cx_linked_list_class = {
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
234 cx_ll_add,
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
235 cx_ll_insert,
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
236 cx_ll_remove,
439
9a5adedd6de6 add high-level function cxListAt()
Mike Becker <universe@uap-core.de>
parents: 438
diff changeset
237 cx_ll_at,
404
86ebc3745e62 adds cxListLast
Mike Becker <universe@uap-core.de>
parents: 403
diff changeset
238 cx_ll_find,
86ebc3745e62 adds cxListLast
Mike Becker <universe@uap-core.de>
parents: 403
diff changeset
239 cx_ll_last
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
240 };
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
241
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
242 CxList cxLinkedListCreate(CxAllocator allocator, CxListComparator comparator, size_t item_size) {
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
243 cx_linked_list *list = cxMalloc(allocator, sizeof(cx_linked_list));
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
244 if (list == NULL)
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
245 return NULL;
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
246
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
247 list->base.cl = &cx_linked_list_class;
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
248 list->base.allocator = allocator;
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
249 list->base.cmpfunc = comparator;
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
250 list->base.itemsize = item_size;
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
251 list->base.capacity = SIZE_MAX;
441
7d5a06e32aa8 change cxLinkedListCreate() setting all fields instead of calling cxListRecalculateSize()
Mike Becker <universe@uap-core.de>
parents: 440
diff changeset
252 list->base.size = 0;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
253
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
254 list->begin = NULL;
441
7d5a06e32aa8 change cxLinkedListCreate() setting all fields instead of calling cxListRecalculateSize()
Mike Becker <universe@uap-core.de>
parents: 440
diff changeset
255 list->end = NULL;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
256
441
7d5a06e32aa8 change cxLinkedListCreate() setting all fields instead of calling cxListRecalculateSize()
Mike Becker <universe@uap-core.de>
parents: 440
diff changeset
257 return (CxList) list;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
258 }
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
259
409
5d167af0eadb adds cxLinkedListDestroy prototype
Mike Becker <universe@uap-core.de>
parents: 408
diff changeset
260 void cxLinkedListDestroy(CxList list) {
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
261 cx_linked_list *ll = (cx_linked_list *) list;
436
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
262
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
263 cx_linked_list_node *node = ll->begin;
436
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
264 while (node) {
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
265 void *next = node->next;
436
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
266 cxFree(list->allocator, node);
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
267 node = next;
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
268 }
ca9ce2297c29 add node destruction in cxLinkedListDestroy()
Mike Becker <universe@uap-core.de>
parents: 435
diff changeset
269
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
270 cxFree(list->allocator, list);
409
5d167af0eadb adds cxLinkedListDestroy prototype
Mike Becker <universe@uap-core.de>
parents: 408
diff changeset
271 }
5d167af0eadb adds cxLinkedListDestroy prototype
Mike Becker <universe@uap-core.de>
parents: 408
diff changeset
272
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
273 size_t cxLinkedListRecalculateSize(CxList list) {
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
274 cx_linked_list *ll = (cx_linked_list *) list;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
275
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
276 if (ll->begin == NULL) {
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
277 ll->base.size = 0;
407
b447539ec255 simplifies linked list descriptor
Mike Becker <universe@uap-core.de>
parents: 406
diff changeset
278 ll->end = NULL;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
279 return 0;
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
280 } else {
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
281 cx_linked_list_node *cur = ll->begin;
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
282 cx_linked_list_node *last;
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
283 size_t size = 0;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
284 do {
407
b447539ec255 simplifies linked list descriptor
Mike Becker <universe@uap-core.de>
parents: 406
diff changeset
285 last = cur;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
286 size++;
446
668757098b73 remove unnecessary fields from linked list node and simplifies cx_ll_add()
Mike Becker <universe@uap-core.de>
parents: 441
diff changeset
287 } while ((cur = cur->next) != NULL);
407
b447539ec255 simplifies linked list descriptor
Mike Becker <universe@uap-core.de>
parents: 406
diff changeset
288 ll->end = last;
435
0fe204d50f54 change inheritance model for lists
Mike Becker <universe@uap-core.de>
parents: 428
diff changeset
289 ll->base.size = size;
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
290 return size;
398
8d506ed6c1c0 adds first draft for linked list implementation
Mike Becker <universe@uap-core.de>
parents:
diff changeset
291 }
406
9cbea761fbf7 adds cxLinkedListWrap and cxLinkedListRecalculateSize
Mike Becker <universe@uap-core.de>
parents: 404
diff changeset
292 }

mercurial