|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
1 #include "list.h" |
29 #include "list.h" |
2 |
30 |
3 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { |
31 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) { |
4 UcxList *ret = NULL; |
32 UcxList *ret = NULL; |
5 while (l != NULL) { |
33 while (l != NULL) { |
11 l = l->next; |
39 l = l->next; |
12 } |
40 } |
13 return ret; |
41 return ret; |
14 } |
42 } |
15 |
43 |
16 int ucx_list_equals(UcxList *l1, UcxList *l2, cmp_func fnc, void* data) { |
44 int ucx_list_equals(const UcxList *l1, const UcxList *l2, |
|
45 cmp_func fnc, void* data) { |
17 if (l1 == l2) return 1; |
46 if (l1 == l2) return 1; |
18 |
47 |
19 while (l1 != NULL && l2 != NULL) { |
48 while (l1 != NULL && l2 != NULL) { |
20 if (fnc == NULL) { |
49 if (fnc == NULL) { |
21 if (l1->data != l2->data) return 0; |
50 if (l1->data != l2->data) return 0; |
71 last->next = l2; |
100 last->next = l2; |
72 return l1; |
101 return l1; |
73 } |
102 } |
74 } |
103 } |
75 |
104 |
76 UcxList *ucx_list_last(UcxList *l) { |
105 UcxList *ucx_list_last(const UcxList *l) { |
77 if (l == NULL) return NULL; |
106 if (l == NULL) return NULL; |
78 |
107 |
79 UcxList *e = l; |
108 const UcxList *e = l; |
80 while (e->next != NULL) { |
109 while (e->next != NULL) { |
81 e = e->next; |
110 e = e->next; |
82 } |
111 } |
83 return e; |
112 return (UcxList*)e; |
84 } |
113 } |
85 |
114 |
86 UcxList *ucx_list_get(UcxList *l, int index) { |
115 UcxList *ucx_list_get(const UcxList *l, int index) { |
87 if (l == NULL) return NULL; |
116 if (l == NULL) return NULL; |
88 |
117 |
89 UcxList *e = l; |
118 const UcxList *e = l; |
90 while (e->next != NULL && index > 0) { |
119 while (e->next != NULL && index > 0) { |
91 e = e->next; |
120 e = e->next; |
92 index--; |
121 index--; |
93 } |
122 } |
94 |
123 |
95 return index == 0 ? e : NULL; |
124 return (UcxList*)(index == 0 ? e : NULL); |
96 } |
125 } |
97 |
126 |
98 size_t ucx_list_size(UcxList *l) { |
127 int ucx_list_contains(UcxList *l, void *elem, cmp_func fnc, void *cmpdata) { |
|
128 UCX_FOREACH(UcxList*, l, e) { |
|
129 if (!fnc(elem, e->data, cmpdata)) { |
|
130 return 1; |
|
131 } |
|
132 } |
|
133 return 0; |
|
134 } |
|
135 |
|
136 size_t ucx_list_size(const UcxList *l) { |
99 if (l == NULL) return 0; |
137 if (l == NULL) return 0; |
100 |
138 |
101 UcxList *e = l; |
139 const UcxList *e = l; |
102 size_t s = 1; |
140 size_t s = 1; |
103 while (e->next != NULL) { |
141 while (e->next != NULL) { |
104 e = e->next; |
142 e = e->next; |
105 s++; |
143 s++; |
106 } |
144 } |
107 |
145 |
108 return s; |
146 return s; |
109 } |
147 } |
110 |
148 |
111 UcxList *ucx_list_sort_merge(int length, |
149 UcxList *ucx_list_sort_merge(int length, |
112 UcxList* ls, UcxList* rs, UcxList* le, UcxList* re, |
150 UcxList* restrict ls, UcxList* restrict le, UcxList* restrict re, |
113 cmp_func fnc, void* data) { |
151 cmp_func fnc, void* data) { |
114 UcxList *sorted[length]; |
152 |
|
153 UcxList** sorted = (UcxList**) malloc(sizeof(UcxList*)*length); |
115 UcxList *rc, *lc; |
154 UcxList *rc, *lc; |
116 |
155 |
117 lc = ls; rc = rs; |
156 lc = ls; rc = le; |
118 int n = 0; |
157 int n = 0; |
119 while (lc != le && rc != re) { |
158 while (lc && lc != le && rc != re) { |
120 if (fnc(lc->data, rc->data, data) <= 0) { |
159 if (fnc(lc->data, rc->data, data) <= 0) { |
121 sorted[n] = lc; |
160 sorted[n] = lc; |
122 lc = lc->next; |
161 lc = lc->next; |
123 } else { |
162 } else { |
124 sorted[n] = rc; |
163 sorted[n] = rc; |
125 rc = rc->next; |
164 rc = rc->next; |
126 } |
165 } |
127 n++; |
166 n++; |
128 } |
167 } |
129 while (lc != le) { |
168 while (lc && lc != le) { |
130 sorted[n] = lc; |
169 sorted[n] = lc; |
131 lc = lc->next; |
170 lc = lc->next; |
132 n++; |
171 n++; |
133 } |
172 } |
134 while (rc != re) { |
173 while (rc && rc != re) { |
135 sorted[n] = rc; |
174 sorted[n] = rc; |
136 rc = rc->next; |
175 rc = rc->next; |
137 n++; |
176 n++; |
138 } |
177 } |
139 |
178 |
141 for (int i = 0 ; i < length-1 ; i++) { |
180 for (int i = 0 ; i < length-1 ; i++) { |
142 sorted[i]->next = sorted[i+1]; |
181 sorted[i]->next = sorted[i+1]; |
143 } |
182 } |
144 sorted[length-1]->next = NULL; |
183 sorted[length-1]->next = NULL; |
145 |
184 |
146 return sorted[0]; |
185 UcxList *ret = sorted[0]; |
|
186 free(sorted); |
|
187 return ret; |
147 } |
188 } |
148 |
189 |
149 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) { |
190 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) { |
150 if (l == NULL) { |
191 if (l == NULL) { |
151 return NULL; |
192 return NULL; |
152 } |
193 } |
153 |
194 |
154 UcxList *lc; |
195 UcxList *lc; |
155 int ln = 1; |
196 int ln = 1; |
156 |
197 |
157 UcxList *ls = l, *le; |
198 UcxList *restrict ls = l, *restrict le, *restrict re; |
158 lc = ls; |
199 lc = ls; |
159 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { |
200 while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) { |
160 lc = lc->next; |
201 lc = lc->next; |
161 ln++; |
202 ln++; |
162 } |
203 } |
163 le = lc->next; |
204 le = lc->next; |
164 |
205 |
165 UcxList *rs = le, *re; |
206 if (le == NULL) { |
166 if (rs == NULL) { |
|
167 return l; // this list is already sorted :) |
207 return l; // this list is already sorted :) |
168 } else { |
208 } else { |
169 UcxList *rc; |
209 UcxList *rc; |
170 int rn = 1; |
210 int rn = 1; |
171 rc = rs; |
211 rc = le; |
172 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { |
212 while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) { |
173 rc = rc->next; |
213 rc = rc->next; |
174 rn++; |
214 rn++; |
175 } |
215 } |
176 re = rc->next; |
216 re = rc->next; |
182 remainder = ucx_list_sort(remainder, fnc, data); |
222 remainder = ucx_list_sort(remainder, fnc, data); |
183 } |
223 } |
184 |
224 |
185 // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them |
225 // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them |
186 UcxList *sorted = ucx_list_sort_merge(ln+rn, |
226 UcxList *sorted = ucx_list_sort_merge(ln+rn, |
187 ls, rs, le, re, |
227 ls, le, re, |
188 fnc, data); |
228 fnc, data); |
189 |
229 |
190 // merge sorted list with (also sorted) remainder |
230 // merge sorted list with (also sorted) remainder |
191 l = ucx_list_sort_merge(ln+rn+remainder_length, |
231 l = ucx_list_sort_merge(ln+rn+remainder_length, |
192 sorted, remainder, NULL, NULL, |
232 sorted, remainder, NULL, fnc, data); |
193 fnc, data); |
|
194 |
233 |
195 return l; |
234 return l; |
196 } |
235 } |
197 } |
236 } |
198 |
237 |