add isl_*_list_drop
[platform/upstream/isl.git] / isl_list_templ.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2011      INRIA Saclay
4  *
5  * Use of this software is governed by the GNU LGPLv2.1 license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
11  */
12
13 #define xCAT(A,B) A ## B
14 #define CAT(A,B) xCAT(A,B)
15 #undef EL
16 #define EL CAT(isl_,BASE)
17 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
18 #define FN(TYPE,NAME) xFN(TYPE,NAME)
19 #define xLIST(EL) EL ## _list
20 #define LIST(EL) xLIST(EL)
21
22 isl_ctx *FN(LIST(EL),get_ctx)(__isl_keep LIST(EL) *list)
23 {
24         return list ? list->ctx : NULL;
25 }
26
27 __isl_give LIST(EL) *FN(LIST(EL),alloc)(isl_ctx *ctx, int n)
28 {
29         LIST(EL) *list;
30
31         if (n < 0)
32                 isl_die(ctx, isl_error_invalid,
33                         "cannot create list of negative length",
34                         return NULL);
35         list = isl_alloc(ctx, LIST(EL),
36                          sizeof(LIST(EL)) + (n - 1) * sizeof(struct EL *));
37         if (!list)
38                 return NULL;
39
40         list->ctx = ctx;
41         isl_ctx_ref(ctx);
42         list->ref = 1;
43         list->size = n;
44         list->n = 0;
45         return list;
46 }
47
48 __isl_give LIST(EL) *FN(LIST(EL),copy)(__isl_keep LIST(EL) *list)
49 {
50         if (!list)
51                 return NULL;
52
53         list->ref++;
54         return list;
55 }
56
57 __isl_give LIST(EL) *FN(LIST(EL),dup)(__isl_keep LIST(EL) *list)
58 {
59         int i;
60         LIST(EL) *dup;
61
62         if (!list)
63                 return NULL;
64
65         dup = FN(LIST(EL),alloc)(FN(LIST(EL),get_ctx)(list), list->n);
66         if (!dup)
67                 return NULL;
68         for (i = 0; i < list->n; ++i)
69                 dup = FN(LIST(EL),add)(dup, FN(EL,copy)(list->p[i]));
70         return dup;
71 }
72
73 __isl_give LIST(EL) *FN(LIST(EL),cow)(__isl_take LIST(EL) *list)
74 {
75         if (!list)
76                 return NULL;
77
78         if (list->ref == 1)
79                 return list;
80         list->ref--;
81         return FN(LIST(EL),dup)(list);
82 }
83
84 /* Make sure "list" has room for at least "n" more pieces.
85  *
86  * If there is only one reference to list, we extend it in place.
87  * Otherwise, we create a new LIST(EL) and copy the elements.
88  */
89 static __isl_give LIST(EL) *FN(LIST(EL),grow)(__isl_take LIST(EL) *list, int n)
90 {
91         isl_ctx *ctx;
92         int i, new_size;
93         LIST(EL) *res;
94
95         if (!list)
96                 return NULL;
97         if (list->n + n <= list->size)
98                 return list;
99
100         ctx = FN(LIST(EL),get_ctx)(list);
101         new_size = ((list->n + n + 1) * 3) / 2;
102         if (list->ref == 1) {
103                 res = isl_realloc(ctx, list, LIST(EL),
104                             sizeof(LIST(EL)) + (new_size - 1) * sizeof(EL *));
105                 if (!res)
106                         return FN(LIST(EL),free)(list);
107                 res->size = new_size;
108                 return res;
109         }
110
111         res = FN(LIST(EL),alloc)(ctx, new_size);
112         if (!res)
113                 return FN(LIST(EL),free)(list);
114
115         for (i = 0; i < list->n; ++i)
116                 res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
117
118         FN(LIST(EL),free)(list);
119         return res;
120 }
121
122 __isl_give LIST(EL) *FN(LIST(EL),add)(__isl_take LIST(EL) *list,
123         __isl_take struct EL *el)
124 {
125         list = FN(LIST(EL),grow)(list, 1);
126         if (!list || !el)
127                 goto error;
128         list->p[list->n] = el;
129         list->n++;
130         return list;
131 error:
132         FN(EL,free)(el);
133         FN(LIST(EL),free)(list);
134         return NULL;
135 }
136
137 /* Remove the "n" elements starting at "first" from "list".
138  */
139 __isl_give LIST(EL) *FN(LIST(EL),drop)(__isl_take LIST(EL) *list,
140         unsigned first, unsigned n)
141 {
142         int i;
143
144         if (!list)
145                 return NULL;
146         if (first + n > list->n || first + n < first)
147                 isl_die(list->ctx, isl_error_invalid,
148                         "index out of bounds", return FN(LIST(EL),free)(list));
149         if (n == 0)
150                 return list;
151         list = FN(LIST(EL),cow)(list);
152         if (!list)
153                 return NULL;
154         for (i = 0; i < n; ++i)
155                 FN(EL,free)(list->p[first + i]);
156         for (i = first; i + n < list->n; ++i)
157                 list->p[i] = list->p[i + n];
158         list->n -= n;
159         return list;
160 }
161
162 void *FN(LIST(EL),free)(__isl_take LIST(EL) *list)
163 {
164         int i;
165
166         if (!list)
167                 return NULL;
168
169         if (--list->ref > 0)
170                 return NULL;
171
172         isl_ctx_deref(list->ctx);
173         for (i = 0; i < list->n; ++i)
174                 FN(EL,free)(list->p[i]);
175         free(list);
176
177         return NULL;
178 }
179
180 int FN(FN(LIST(EL),n),BASE)(__isl_keep LIST(EL) *list)
181 {
182         return list ? list->n : 0;
183 }
184
185 __isl_give EL *FN(FN(LIST(EL),get),BASE)(__isl_keep LIST(EL) *list, int index)
186 {
187         if (!list)
188                 return NULL;
189         if (index < 0 || index >= list->n)
190                 isl_die(list->ctx, isl_error_invalid,
191                         "index out of bounds", return NULL);
192         return FN(EL,copy)(list->p[index]);
193 }
194
195 /* Replace the element at position "index" in "list" by "el".
196  */
197 __isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
198         int index, __isl_take EL *el)
199 {
200         if (!list || !el)
201                 goto error;
202         if (index < 0 || index >= list->n)
203                 isl_die(list->ctx, isl_error_invalid,
204                         "index out of bounds", goto error);
205         if (list->p[index] == el) {
206                 FN(EL,free)(el);
207                 return list;
208         }
209         list = FN(LIST(EL),cow)(list);
210         if (!list)
211                 goto error;
212         FN(EL,free)(list->p[index]);
213         list->p[index] = el;
214         return list;
215 error:
216         FN(EL,free)(el);
217         FN(LIST(EL),free)(list);
218         return NULL;
219 }
220
221 int FN(LIST(EL),foreach)(__isl_keep LIST(EL) *list,
222         int (*fn)(__isl_take EL *el, void *user), void *user)
223 {
224         int i;
225
226         if (!list)
227                 return -1;
228
229         for (i = 0; i < list->n; ++i) {
230                 EL *el = FN(EL,copy(list->p[i]));
231                 if (!el)
232                         return -1;
233                 if (fn(el, user) < 0)
234                         return -1;
235         }
236
237         return 0;
238 }
239
240 __isl_give LIST(EL) *FN(FN(LIST(EL),from),BASE)(__isl_take EL *el)
241 {
242         isl_ctx *ctx;
243         LIST(EL) *list;
244
245         if (!el)
246                 return NULL;
247         ctx = FN(EL,get_ctx)(el);
248         list = FN(LIST(EL),alloc)(ctx, 1);
249         if (!list)
250                 goto error;
251         list = FN(LIST(EL),add)(list, el);
252         return list;
253 error:
254         FN(EL,free)(el);
255         return NULL;
256 }
257
258 __isl_give LIST(EL) *FN(LIST(EL),concat)(__isl_take LIST(EL) *list1,
259         __isl_take LIST(EL) *list2)
260 {
261         int i;
262         isl_ctx *ctx;
263         LIST(EL) *res;
264
265         if (!list1 || !list2)
266                 goto error;
267
268         ctx = FN(LIST(EL),get_ctx)(list1);
269         res = FN(LIST(EL),alloc)(ctx, list1->n + list2->n);
270         for (i = 0; i < list1->n; ++i)
271                 res = FN(LIST(EL),add)(res, FN(EL,copy)(list1->p[i]));
272         for (i = 0; i < list2->n; ++i)
273                 res = FN(LIST(EL),add)(res, FN(EL,copy)(list2->p[i]));
274
275         FN(LIST(EL),free)(list1);
276         FN(LIST(EL),free)(list2);
277         return res;
278 error:
279         FN(LIST(EL),free)(list1);
280         FN(LIST(EL),free)(list2);
281         return NULL;
282 }
283
284 __isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
285         __isl_take isl_printer *p, __isl_keep LIST(EL) *list)
286 {
287         int i;
288
289         if (!p || !list)
290                 goto error;
291         p = isl_printer_print_str(p, "(");
292         for (i = 0; i < list->n; ++i) {
293                 if (i)
294                         p = isl_printer_print_str(p, ",");
295                 p = CAT(isl_printer_print_,BASE)(p, list->p[i]);
296         }
297         p = isl_printer_print_str(p, ")");
298         return p;
299 error:
300         isl_printer_free(p);
301         return NULL;
302 }
303
304 void FN(LIST(EL),dump)(__isl_keep LIST(EL) *list)
305 {
306         isl_printer *printer;
307
308         if (!list)
309                 return;
310
311         printer = isl_printer_to_file(FN(LIST(EL),get_ctx)(list), stderr);
312         printer = CAT(isl_printer_print_,LIST(BASE))(printer, list);
313         printer = isl_printer_end_line(printer);
314
315         isl_printer_free(printer);
316 }