client: Don't forget to init and destroy mutex
[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 #include <stdarg.h>
28
29 #include "wayland-util.h"
30 #include "wayland-private.h"
31
32 WL_EXPORT void
33 wl_list_init(struct wl_list *list)
34 {
35         list->prev = list;
36         list->next = list;
37 }
38
39 WL_EXPORT void
40 wl_list_insert(struct wl_list *list, struct wl_list *elm)
41 {
42         elm->prev = list;
43         elm->next = list->next;
44         list->next = elm;
45         elm->next->prev = elm;
46 }
47
48 WL_EXPORT void
49 wl_list_remove(struct wl_list *elm)
50 {
51         elm->prev->next = elm->next;
52         elm->next->prev = elm->prev;
53         elm->next = NULL;
54         elm->prev = NULL;
55 }
56
57 WL_EXPORT int
58 wl_list_length(struct wl_list *list)
59 {
60         struct wl_list *e;
61         int count;
62
63         count = 0;
64         e = list->next;
65         while (e != list) {
66                 e = e->next;
67                 count++;
68         }
69
70         return count;
71 }
72
73 WL_EXPORT int
74 wl_list_empty(struct wl_list *list)
75 {
76         return list->next == list;
77 }
78
79 WL_EXPORT void
80 wl_list_insert_list(struct wl_list *list, struct wl_list *other)
81 {
82         if (wl_list_empty(other))
83                 return;
84
85         other->next->prev = list;
86         other->prev->next = list->next;
87         list->next->prev = other->prev;
88         list->next = other->next;
89 }
90
91 WL_EXPORT void
92 wl_array_init(struct wl_array *array)
93 {
94         memset(array, 0, sizeof *array);
95 }
96
97 WL_EXPORT void
98 wl_array_release(struct wl_array *array)
99 {
100         free(array->data);
101 }
102
103 WL_EXPORT void *
104 wl_array_add(struct wl_array *array, size_t size)
105 {
106         size_t alloc;
107         void *data, *p;
108
109         if (array->alloc > 0)
110                 alloc = array->alloc;
111         else
112                 alloc = 16;
113
114         while (alloc < array->size + size)
115                 alloc *= 2;
116
117         if (array->alloc < alloc) {
118                 if (array->alloc > 0)
119                         data = realloc(array->data, alloc);
120                 else
121                         data = malloc(alloc);
122
123                 if (data == NULL)
124                         return 0;
125                 array->data = data;
126                 array->alloc = alloc;
127         }
128
129         p = array->data + array->size;
130         array->size += size;
131
132         return p;
133 }
134
135 WL_EXPORT void
136 wl_array_copy(struct wl_array *array, struct wl_array *source)
137 {
138         array->size = 0;
139         wl_array_add(array, source->size);
140         memcpy(array->data, source->data, source->size);
141 }
142
143 union map_entry {
144         uintptr_t next;
145         void *data;
146 };
147
148 WL_EXPORT void
149 wl_map_init(struct wl_map *map)
150 {
151         memset(map, 0, sizeof *map);
152 }
153
154 WL_EXPORT void
155 wl_map_release(struct wl_map *map)
156 {
157         wl_array_release(&map->client_entries);
158         wl_array_release(&map->server_entries);
159 }
160
161 WL_EXPORT uint32_t
162 wl_map_insert_new(struct wl_map *map, uint32_t side, void *data)
163 {
164         union map_entry *start, *entry;
165         struct wl_array *entries;
166         uint32_t base;
167
168         if (side == WL_MAP_CLIENT_SIDE) {
169                 entries = &map->client_entries;
170                 base = 0;
171         } else {
172                 entries = &map->server_entries;
173                 base = WL_SERVER_ID_START;
174         }
175
176         if (map->free_list) {
177                 start = entries->data;
178                 entry = &start[map->free_list >> 1];
179                 map->free_list = entry->next;
180         } else {
181                 entry = wl_array_add(entries, sizeof *entry);
182                 start = entries->data;
183         }
184
185         entry->data = data;
186
187         return (entry - start) + base;
188 }
189
190 WL_EXPORT int
191 wl_map_insert_at(struct wl_map *map, uint32_t i, void *data)
192 {
193         union map_entry *start;
194         uint32_t count;
195         struct wl_array *entries;
196
197         if (i < WL_SERVER_ID_START) {
198                 entries = &map->client_entries;
199         } else {
200                 entries = &map->server_entries;
201                 i -= WL_SERVER_ID_START;
202         }
203
204         count = entries->size / sizeof *start;
205         if (count < i)
206                 return -1;
207
208         if (count == i)
209                 wl_array_add(entries, sizeof *start);
210
211         start = entries->data;
212         start[i].data = data;
213
214         return 0;
215 }
216
217 WL_EXPORT int
218 wl_map_reserve_new(struct wl_map *map, uint32_t i)
219 {
220         union map_entry *start;
221         uint32_t count;
222         struct wl_array *entries;
223
224         if (i < WL_SERVER_ID_START) {
225                 entries = &map->client_entries;
226         } else {
227                 entries = &map->server_entries;
228                 i -= WL_SERVER_ID_START;
229         }
230
231         count = entries->size / sizeof *start;
232
233         if (count < i)
234                 return -1;
235
236         if (count == i) {
237                 wl_array_add(entries, sizeof *start);
238                 start = entries->data;
239                 start[i].data = NULL;
240         } else {
241                 start = entries->data;
242                 if (start[i].data != NULL) {
243                         return -1;
244                 }
245         }
246
247         return 0;
248 }
249
250 WL_EXPORT void
251 wl_map_remove(struct wl_map *map, uint32_t i)
252 {
253         union map_entry *start;
254         struct wl_array *entries;
255
256         if (i < WL_SERVER_ID_START) {
257                 entries = &map->client_entries;
258         } else {
259                 entries = &map->server_entries;
260                 i -= WL_SERVER_ID_START;
261         }
262
263         start = entries->data;
264         start[i].next = map->free_list;
265         map->free_list = (i << 1) | 1;
266 }
267
268 WL_EXPORT void *
269 wl_map_lookup(struct wl_map *map, uint32_t i)
270 {
271         union map_entry *start;
272         uint32_t count;
273         struct wl_array *entries;
274
275         if (i < WL_SERVER_ID_START) {
276                 entries = &map->client_entries;
277         } else {
278                 entries = &map->server_entries;
279                 i -= WL_SERVER_ID_START;
280         }
281
282         start = entries->data;
283         count = entries->size / sizeof *start;
284
285         if (i < count && !(start[i].next & 1))
286                 return start[i].data;
287
288         return NULL;
289 }
290
291 static void
292 for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
293 {
294         union map_entry *start, *end, *p;
295
296         start = entries->data;
297         end = (union map_entry *) ((char *) entries->data + entries->size);
298
299         for (p = start; p < end; p++)
300                 if (p->data && !(p->next & 1))
301                         func(p->data, data);
302 }
303
304 WL_EXPORT void
305 wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
306 {
307         for_each_helper(&map->client_entries, func, data);
308         for_each_helper(&map->server_entries, func, data);
309 }
310
311 static void
312 wl_log_noop_handler(const char *fmt, va_list arg)
313 {
314 }
315
316 wl_log_func_t wl_log_handler = wl_log_noop_handler;
317
318 void
319 wl_log(const char *fmt, ...)
320 {
321         va_list argp;
322
323         va_start(argp, fmt);
324         wl_log_handler(fmt, argp);
325         va_end(argp);
326 }