util: clear pointers on wl_list_remove()
[profile/ivi/wayland.git] / src / wayland-util.c
1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2011 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <string.h>
27
28 #include "wayland-util.h"
29 #include "wayland-private.h"
30
31 WL_EXPORT void
32 wl_list_init(struct wl_list *list)
33 {
34         list->prev = list;
35         list->next = list;
36 }
37
38 WL_EXPORT void
39 wl_list_insert(struct wl_list *list, struct wl_list *elm)
40 {
41         elm->prev = list;
42         elm->next = list->next;
43         list->next = elm;
44         elm->next->prev = elm;
45 }
46
47 WL_EXPORT void
48 wl_list_remove(struct wl_list *elm)
49 {
50         elm->prev->next = elm->next;
51         elm->next->prev = elm->prev;
52         elm->next = NULL;
53         elm->prev = NULL;
54 }
55
56 WL_EXPORT int
57 wl_list_length(struct wl_list *list)
58 {
59         struct wl_list *e;
60         int count;
61
62         count = 0;
63         e = list->next;
64         while (e != list) {
65                 e = e->next;
66                 count++;
67         }
68
69         return count;
70 }
71
72 WL_EXPORT int
73 wl_list_empty(struct wl_list *list)
74 {
75         return list->next == list;
76 }
77
78 WL_EXPORT void
79 wl_list_insert_list(struct wl_list *list, struct wl_list *other)
80 {
81         other->next->prev = list;
82         other->prev->next = list->next;
83         list->next->prev = other->prev;
84         list->next = other->next;
85 }
86
87 WL_EXPORT void
88 wl_array_init(struct wl_array *array)
89 {
90         memset(array, 0, sizeof *array);
91 }
92
93 WL_EXPORT void
94 wl_array_release(struct wl_array *array)
95 {
96         free(array->data);
97 }
98
99 WL_EXPORT void *
100 wl_array_add(struct wl_array *array, int size)
101 {
102         int alloc;
103         void *data, *p;
104
105         if (array->alloc > 0)
106                 alloc = array->alloc;
107         else
108                 alloc = 16;
109
110         while (alloc < array->size + size)
111                 alloc *= 2;
112
113         if (array->alloc < alloc) {
114                 if (array->alloc > 0)
115                         data = realloc(array->data, alloc);
116                 else
117                         data = malloc(alloc);
118
119                 if (data == NULL)
120                         return 0;
121                 array->data = data;
122                 array->alloc = alloc;
123         }
124
125         p = array->data + array->size;
126         array->size += size;
127
128         return p;
129 }
130
131 WL_EXPORT void
132 wl_array_copy(struct wl_array *array, struct wl_array *source)
133 {
134         array->size = 0;
135         wl_array_add(array, source->size);
136         memcpy(array->data, source->data, source->size);
137 }
138
139 union map_entry {
140         uintptr_t next;
141         void *data;
142 };
143
144 WL_EXPORT void
145 wl_map_init(struct wl_map *map)
146 {
147         memset(map, 0, sizeof *map);
148 }
149
150 WL_EXPORT void
151 wl_map_release(struct wl_map *map)
152 {
153         wl_array_release(&map->client_entries);
154         wl_array_release(&map->server_entries);
155 }
156
157 WL_EXPORT uint32_t
158 wl_map_insert_new(struct wl_map *map, uint32_t side, void *data)
159 {
160         union map_entry *start, *entry;
161         struct wl_array *entries;
162         uint32_t base;
163
164         if (side == WL_MAP_CLIENT_SIDE) {
165                 entries = &map->client_entries;
166                 base = 0;
167         } else {
168                 entries = &map->server_entries;
169                 base = WL_SERVER_ID_START;
170         }
171
172         if (map->free_list) {
173                 start = entries->data;
174                 entry = &start[map->free_list >> 1];
175                 map->free_list = entry->next;
176         } else {
177                 entry = wl_array_add(entries, sizeof *entry);
178                 start = entries->data;
179         }
180
181         entry->data = data;
182
183         return (entry - start) + base;
184 }
185
186 WL_EXPORT int
187 wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
188 {
189         union map_entry *start;
190         uint32_t count;
191         struct wl_array *entries;
192
193         if (i < WL_SERVER_ID_START) {
194                 entries = &map->client_entries;
195         } else {
196                 entries = &map->server_entries;
197                 i -= WL_SERVER_ID_START;
198         }
199
200         count = entries->size / sizeof *start;
201         if (count < i)
202                 return -1;
203
204         if (count == i)
205                 wl_array_add(entries, sizeof *start);
206
207         start = entries->data;
208         start[i].data = data;
209
210         return 0;
211 }
212
213 WL_EXPORT void
214 wl_map_remove(struct wl_map *map, uint32_t i)
215 {
216         union map_entry *start;
217         struct wl_array *entries;
218
219         if (i < WL_SERVER_ID_START) {
220                 entries = &map->client_entries;
221         } else {
222                 entries = &map->server_entries;
223                 i -= WL_SERVER_ID_START;
224         }
225
226         start = entries->data;
227         start[i].next = map->free_list;
228         map->free_list = (i << 1) | 1;
229 }
230
231 WL_EXPORT void *
232 wl_map_lookup(struct wl_map *map, uint32_t i)
233 {
234         union map_entry *start;
235         uint32_t count;
236         struct wl_array *entries;
237
238         if (i < WL_SERVER_ID_START) {
239                 entries = &map->client_entries;
240         } else {
241                 entries = &map->server_entries;
242                 i -= WL_SERVER_ID_START;
243         }
244
245         start = entries->data;
246         count = entries->size / sizeof *start;
247
248         if (i < count && !(start[i].next & 1))
249                 return start[i].data;
250
251         return NULL;
252 }
253
254 static void
255 for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
256 {
257         union map_entry *start, *end, *p;
258
259         start = entries->data;
260         end = (union map_entry *) ((char *) entries->data + entries->size);
261
262         for (p = start; p < end; p++)
263                 if (p->data && !(p->next & 1))
264                         func(p->data, data);
265 }
266
267 WL_EXPORT void
268 wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
269 {
270         for_each_helper(&map->client_entries, func, data);
271         for_each_helper(&map->server_entries, func, data);
272 }