887a92f53e7c7fd80e4da4b68c726a7275a173a3
[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 __isl_give LIST(EL) *FN(LIST(EL),add)(__isl_take LIST(EL) *list,
85         __isl_take struct EL *el)
86 {
87         if (!list || !el)
88                 goto error;
89         isl_assert(list->ctx, list->n < list->size, goto error);
90         list->p[list->n] = el;
91         list->n++;
92         return list;
93 error:
94         FN(EL,free)(el);
95         FN(LIST(EL),free)(list);
96         return NULL;
97 }
98
99 void *FN(LIST(EL),free)(__isl_take LIST(EL) *list)
100 {
101         int i;
102
103         if (!list)
104                 return NULL;
105
106         if (--list->ref > 0)
107                 return NULL;
108
109         isl_ctx_deref(list->ctx);
110         for (i = 0; i < list->n; ++i)
111                 FN(EL,free)(list->p[i]);
112         free(list);
113
114         return NULL;
115 }
116
117 int FN(FN(LIST(EL),n),BASE)(__isl_keep LIST(EL) *list)
118 {
119         return list ? list->n : 0;
120 }
121
122 __isl_give EL *FN(FN(LIST(EL),get),BASE)(__isl_keep LIST(EL) *list, int index)
123 {
124         if (!list)
125                 return NULL;
126         if (index < 0 || index >= list->n)
127                 isl_die(list->ctx, isl_error_invalid,
128                         "index out of bounds", return NULL);
129         return FN(EL,copy)(list->p[index]);
130 }
131
132 /* Replace the element at position "index" in "list" by "el".
133  */
134 __isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
135         int index, __isl_take EL *el)
136 {
137         if (!list || !el)
138                 goto error;
139         if (index < 0 || index >= list->n)
140                 isl_die(list->ctx, isl_error_invalid,
141                         "index out of bounds", goto error);
142         if (list->p[index] == el) {
143                 FN(EL,free)(el);
144                 return list;
145         }
146         list = FN(LIST(EL),cow)(list);
147         if (!list)
148                 goto error;
149         FN(EL,free)(list->p[index]);
150         list->p[index] = el;
151         return list;
152 error:
153         FN(EL,free)(el);
154         FN(LIST(EL),free)(list);
155         return NULL;
156 }
157
158 int FN(LIST(EL),foreach)(__isl_keep LIST(EL) *list,
159         int (*fn)(__isl_take EL *el, void *user), void *user)
160 {
161         int i;
162
163         if (!list)
164                 return -1;
165
166         for (i = 0; i < list->n; ++i) {
167                 EL *el = FN(EL,copy(list->p[i]));
168                 if (!el)
169                         return -1;
170                 if (fn(el, user) < 0)
171                         return -1;
172         }
173
174         return 0;
175 }
176
177 __isl_give LIST(EL) *FN(FN(LIST(EL),from),BASE)(__isl_take EL *el)
178 {
179         isl_ctx *ctx;
180         LIST(EL) *list;
181
182         if (!el)
183                 return NULL;
184         ctx = FN(EL,get_ctx)(el);
185         list = FN(LIST(EL),alloc)(ctx, 1);
186         if (!list)
187                 goto error;
188         list = FN(LIST(EL),add)(list, el);
189         return list;
190 error:
191         FN(EL,free)(el);
192         return NULL;
193 }
194
195 __isl_give LIST(EL) *FN(LIST(EL),concat)(__isl_take LIST(EL) *list1,
196         __isl_take LIST(EL) *list2)
197 {
198         int i;
199         isl_ctx *ctx;
200         LIST(EL) *res;
201
202         if (!list1 || !list2)
203                 goto error;
204
205         ctx = FN(LIST(EL),get_ctx)(list1);
206         res = FN(LIST(EL),alloc)(ctx, list1->n + list2->n);
207         for (i = 0; i < list1->n; ++i)
208                 res = FN(LIST(EL),add)(res, FN(EL,copy)(list1->p[i]));
209         for (i = 0; i < list2->n; ++i)
210                 res = FN(LIST(EL),add)(res, FN(EL,copy)(list2->p[i]));
211
212         FN(LIST(EL),free)(list1);
213         FN(LIST(EL),free)(list2);
214         return res;
215 error:
216         FN(LIST(EL),free)(list1);
217         FN(LIST(EL),free)(list2);
218         return NULL;
219 }
220
221 __isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
222         __isl_take isl_printer *p, __isl_keep LIST(EL) *list)
223 {
224         int i;
225
226         if (!p || !list)
227                 goto error;
228         p = isl_printer_print_str(p, "(");
229         for (i = 0; i < list->n; ++i) {
230                 if (i)
231                         p = isl_printer_print_str(p, ",");
232                 p = CAT(isl_printer_print_,BASE)(p, list->p[i]);
233         }
234         p = isl_printer_print_str(p, ")");
235         return p;
236 error:
237         isl_printer_free(p);
238         return NULL;
239 }
240
241 void FN(LIST(EL),dump)(__isl_keep LIST(EL) *list)
242 {
243         isl_printer *printer;
244
245         if (!list)
246                 return;
247
248         printer = isl_printer_to_file(FN(LIST(EL),get_ctx)(list), stderr);
249         printer = CAT(isl_printer_print_,LIST(BASE))(printer, list);
250         printer = isl_printer_end_line(printer);
251
252         isl_printer_free(printer);
253 }