1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 //
6 // Contributor(s):
7 // Marc Ume
8 //
9
10 #include "GmshConfig.h"
11 #if !defined(HAVE_NO_STDINT_H)
12 #include <stdint.h>
13 #elif defined(HAVE_NO_INTPTR_T)
14 typedef unsigned long intptr_t;
15 #endif
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include "MallocUtils.h"
22 #include "ListUtils.h"
23 #include "TreeUtils.h"
24 #include "GmshMessage.h"
25
fcmp_int(const void * a,const void * b)26 int fcmp_int(const void *a, const void *b) { return (*(int *)a - *(int *)b); }
27
fcmp_absint(const void * a,const void * b)28 int fcmp_absint(const void *a, const void *b)
29 {
30 return (abs(*(int *)a) - abs(*(int *)b));
31 }
32
fcmp_double(const void * a,const void * b)33 int fcmp_double(const void *a, const void *b)
34 {
35 double cmp;
36
37 cmp = *(double *)a - *(double *)b;
38 if(cmp > 1.e-16)
39 return 1;
40 else if(cmp < -1.e-16)
41 return -1;
42 else
43 return 0;
44 }
45
List_Create(int n,int incr,int size)46 List_T *List_Create(int n, int incr, int size)
47 {
48 List_T *liste;
49
50 if(n <= 0) n = 1;
51 if(incr <= 0) incr = 1;
52
53 liste = (List_T *)Malloc(sizeof(List_T));
54
55 liste->nmax = 0;
56 liste->incr = incr;
57 liste->size = size;
58 liste->n = 0;
59 liste->isorder = 0;
60 liste->array = nullptr;
61
62 List_Realloc(liste, n);
63 return (liste);
64 }
65
List_Delete(List_T * liste)66 void List_Delete(List_T *liste)
67 {
68 if(!liste) return;
69 Free(liste->array);
70 Free(liste);
71 }
72
List_Realloc(List_T * liste,int n)73 void List_Realloc(List_T *liste, int n)
74 {
75 if(!liste || n <= 0) return;
76
77 if(liste->array == nullptr) {
78 // This does not permit to allocate lists smaller that liste->incr:
79 // liste->nmax = ((n - 1) / liste->incr + 1) * liste->incr;
80 // So this is much better
81 liste->nmax = n;
82 liste->array = (char *)Malloc(liste->nmax * liste->size);
83 }
84 else if(n > liste->nmax) {
85 liste->nmax = ((n - 1) / liste->incr + 1) * liste->incr;
86 liste->array = (char *)Realloc(liste->array, liste->nmax * liste->size);
87 }
88 }
89
List_Add(List_T * liste,void * data)90 void List_Add(List_T *liste, void *data)
91 {
92 if(!liste) return;
93 liste->n++;
94
95 List_Realloc(liste, liste->n);
96 liste->isorder = 0;
97 memcpy(&liste->array[(liste->n - 1) * liste->size], data, liste->size);
98 }
99
List_Add(List_T * liste,int data)100 void List_Add(List_T *liste, int data)
101 {
102 if(!liste) return;
103 List_Add(liste, &data);
104 }
105
List_Nbr(List_T * liste)106 int List_Nbr(List_T *liste)
107 {
108 return liste ? liste->n : 0;
109 }
110
List_Read(List_T * liste,int index,void * data)111 void List_Read(List_T *liste, int index, void *data)
112 {
113 if(!liste || (index < 0) || (index >= liste->n)) {
114 Msg::Error("Wrong list index (read)");
115 index = 0;
116 }
117 memcpy(data, &liste->array[index * liste->size], liste->size);
118 }
119
List_Write(List_T * liste,int index,void * data)120 void List_Write(List_T *liste, int index, void *data)
121 {
122 if(!liste || (index < 0) || (index >= liste->n))
123 Msg::Error("Wrong list index (write)");
124 else {
125 liste->isorder = 0;
126 memcpy(&liste->array[index * liste->size], data, liste->size);
127 }
128 }
129
List_Put(List_T * liste,int index,void * data)130 void List_Put(List_T *liste, int index, void *data)
131 {
132 if(!liste || index < 0)
133 Msg::Error("Wrong list index (put)");
134 else {
135 if(index >= liste->n) {
136 liste->n = index + 1;
137 List_Realloc(liste, liste->n);
138 List_Write(liste, index, data);
139 }
140 else {
141 List_Write(liste, index, data);
142 }
143 }
144 }
145
List_Pop(List_T * liste)146 void List_Pop(List_T *liste)
147 {
148 if(!liste) return;
149 if(liste->n > 0) liste->n--;
150 }
151
List_Pointer(List_T * liste,int index)152 void *List_Pointer(List_T *liste, int index)
153 {
154 if(!liste || (index < 0) || (index >= liste->n)) {
155 Msg::Error("Wrong list index (pointer)");
156 index = 0;
157 }
158 liste->isorder = 0;
159 return (&liste->array[index * liste->size]);
160 }
161
List_Pointer_NoChange(List_T * liste,int index)162 void *List_Pointer_NoChange(List_T *liste, int index)
163 {
164 if(!liste || (index < 0) || (index >= liste->n)) {
165 Msg::Error("Wrong list index (pointer)");
166 index = 0;
167 }
168 return (&liste->array[index * liste->size]);
169 }
170
List_Pointer_Fast(List_T * liste,int index)171 void *List_Pointer_Fast(List_T *liste, int index)
172 {
173 return (&liste->array[index * liste->size]);
174 }
175
List_Sort(List_T * liste,int (* fcmp)(const void * a,const void * b))176 void List_Sort(List_T *liste, int (*fcmp)(const void *a, const void *b))
177 {
178 if(!liste) return;
179 qsort(liste->array, liste->n, liste->size, fcmp);
180 }
181
List_Unique(List_T * liste,int (* fcmp)(const void * a,const void * b))182 void List_Unique(List_T *liste, int (*fcmp)(const void *a, const void *b))
183 {
184 if(!liste) return;
185 if(liste->isorder != 1) {
186 List_Sort(liste, fcmp);
187 liste->isorder = 1;
188 }
189 if(!List_Nbr(liste)) return;
190 int write_index = 0;
191 for(int i = 1; i < List_Nbr(liste); i++) {
192 void *data = List_Pointer(liste, i);
193 if((fcmp(data, (void *)List_Pointer(liste, write_index))))
194 List_Write(liste, ++write_index, data);
195 }
196 liste->n = write_index + 1;
197 }
198
List_Search(List_T * liste,void * data,int (* fcmp)(const void * a,const void * b))199 int List_Search(List_T *liste, void *data,
200 int (*fcmp)(const void *a, const void *b))
201 {
202 if(!liste) return 0;
203 void *ptr;
204
205 if(liste->isorder != 1) {
206 List_Sort(liste, fcmp);
207 liste->isorder = 1;
208 }
209 ptr = (void *)bsearch(data, liste->array, liste->n, liste->size, fcmp);
210 if(ptr == nullptr) return (0);
211 return (1);
212 }
213
List_ISearchSeq(List_T * liste,void * data,int (* fcmp)(const void * a,const void * b))214 int List_ISearchSeq(List_T *liste, void *data,
215 int (*fcmp)(const void *a, const void *b))
216 {
217 if(!liste) return -1;
218 int i = 0;
219 while((i < List_Nbr(liste)) && fcmp(data, (void *)List_Pointer(liste, i)))
220 i++;
221 if(i == List_Nbr(liste)) i = -1;
222 return i;
223 }
224
List_PQuery(List_T * liste,void * data,int (* fcmp)(const void * a,const void * b))225 void *List_PQuery(List_T *liste, void *data,
226 int (*fcmp)(const void *a, const void *b))
227 {
228 if(!liste) return nullptr;
229 void *ptr;
230 if(liste->isorder != 1) List_Sort(liste, fcmp);
231 liste->isorder = 1;
232 ptr = (void *)bsearch(data, liste->array, liste->n, liste->size, fcmp);
233 return (ptr);
234 }
235
List_Suppress(List_T * liste,void * data,int (* fcmp)(const void * a,const void * b))236 int List_Suppress(List_T *liste, void *data,
237 int (*fcmp)(const void *a, const void *b))
238 {
239 if(!liste) return 0;
240 char *ptr = (char *)List_PQuery(liste, data, fcmp);
241 if(ptr == nullptr) return (0);
242 liste->n--;
243 int len = liste->n - (((intptr_t)ptr - (intptr_t)liste->array) / liste->size);
244 if(len > 0) memmove(ptr, ptr + liste->size, len * liste->size);
245 return (1);
246 }
247
List_PSuppress(List_T * liste,int index)248 int List_PSuppress(List_T *liste, int index)
249 {
250 if(!liste) return 0;
251 char *ptr = (char *)List_Pointer_NoChange(liste, index);
252 if(ptr == nullptr) return (0);
253 liste->n--;
254 int len = liste->n - (((intptr_t)ptr - (intptr_t)liste->array) / liste->size);
255 if(len > 0) memmove(ptr, ptr + liste->size, len * liste->size);
256 return (1);
257 }
258
List_Invert(List_T * a,List_T * b)259 void List_Invert(List_T *a, List_T *b)
260 {
261 if(!a || !b) return;
262 int i, N;
263 N = List_Nbr(a);
264 for(i = 0; i < N; i++) {
265 List_Add(b, List_Pointer(a, N - i - 1));
266 }
267 }
268
List_Reset(List_T * liste)269 void List_Reset(List_T *liste)
270 {
271 if(!liste) return;
272 liste->n = 0;
273 }
274
List_Action(List_T * liste,void (* action)(void * data,void * dummy))275 void List_Action(List_T *liste, void (*action)(void *data, void *dummy))
276 {
277 if(!liste) return;
278 int i, dummy;
279 for(i = 0; i < List_Nbr(liste); i++)
280 (*action)(List_Pointer_NoChange(liste, i), &dummy);
281 }
282
List_Copy(List_T * a,List_T * b)283 void List_Copy(List_T *a, List_T *b)
284 {
285 if(!a || !b) return;
286 int i, N;
287 N = List_Nbr(a);
288 for(i = 0; i < N; i++) {
289 List_Add(b, List_Pointer(a, i));
290 }
291 }
292
List_Remove(List_T * a,int i)293 void List_Remove(List_T *a, int i)
294 {
295 if(!a) return;
296 memcpy(&a->array[i * a->size], &a->array[(i + 1) * a->size],
297 a->size * (a->n - i - 1));
298 a->n--;
299 }
300
301 // insert a in b before i
List_Insert_In_List(List_T * a,int i,List_T * b)302 void List_Insert_In_List(List_T *a, int i, List_T *b)
303 {
304 if(!a || !b) return;
305 int oldn = b->n;
306 b->n += a->n;
307 List_Realloc(b, b->n);
308 for(int j = 0; j < oldn - i; j++)
309 memcpy(List_Pointer_Fast(b, b->n - j - 1),
310 List_Pointer_Fast(b, oldn - j - 1), b->size);
311 for(int j = 0; j < a->n; j++)
312 memcpy(List_Pointer_Fast(b, i + j), List_Pointer_Fast(a, j), b->size);
313 }
314
ListOfDouble2ListOfInt(List_T * dList)315 List_T *ListOfDouble2ListOfInt(List_T *dList)
316 {
317 int n = List_Nbr(dList);
318 List_T *iList = List_Create(n, n, sizeof(int));
319 for(int i = 0; i < n; i++) {
320 double d;
321 List_Read(dList, i, &d);
322 int j = (int)d;
323 List_Add(iList, &j);
324 }
325 return iList;
326 }
327