• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright © 2008-2011 Kristian Høgsberg
3   * Copyright © 2011 Intel Corporation
4   *
5   * Permission is hereby granted, free of charge, to any person obtaining
6   * a copy of this software and associated documentation files (the
7   * "Software"), to deal in the Software without restriction, including
8   * without limitation the rights to use, copy, modify, merge, publish,
9   * distribute, sublicense, and/or sell copies of the Software, and to
10   * permit persons to whom the Software is furnished to do so, subject to
11   * the following conditions:
12   *
13   * The above copyright notice and this permission notice (including the
14   * next paragraph) shall be included in all copies or substantial
15   * portions of the Software.
16   *
17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20   * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21   * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22   * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  
27  #include <stdlib.h>
28  #include <stdint.h>
29  #include <stdio.h>
30  #include <string.h>
31  #include <stdarg.h>
32  
33  #include "wayland-util.h"
34  #include "wayland-private.h"
35  
36  WL_EXPORT void
wl_list_init(struct wl_list * list)37  wl_list_init(struct wl_list *list)
38  {
39  	list->prev = list;
40  	list->next = list;
41  }
42  
43  WL_EXPORT void
wl_list_insert(struct wl_list * list,struct wl_list * elm)44  wl_list_insert(struct wl_list *list, struct wl_list *elm)
45  {
46  	elm->prev = list;
47  	elm->next = list->next;
48  	list->next = elm;
49  	elm->next->prev = elm;
50  }
51  
52  WL_EXPORT void
wl_list_remove(struct wl_list * elm)53  wl_list_remove(struct wl_list *elm)
54  {
55  	elm->prev->next = elm->next;
56  	elm->next->prev = elm->prev;
57  	elm->next = NULL;
58  	elm->prev = NULL;
59  }
60  
61  WL_EXPORT int
wl_list_length(const struct wl_list * list)62  wl_list_length(const struct wl_list *list)
63  {
64  	struct wl_list *e;
65  	int count;
66  
67  	count = 0;
68  	e = list->next;
69  	while (e != list) {
70  		e = e->next;
71  		count++;
72  	}
73  
74  	return count;
75  }
76  
77  WL_EXPORT int
wl_list_empty(const struct wl_list * list)78  wl_list_empty(const struct wl_list *list)
79  {
80  	return list->next == list;
81  }
82  
83  WL_EXPORT void
wl_list_insert_list(struct wl_list * list,struct wl_list * other)84  wl_list_insert_list(struct wl_list *list, struct wl_list *other)
85  {
86  	if (wl_list_empty(other))
87  		return;
88  
89  	other->next->prev = list;
90  	other->prev->next = list->next;
91  	list->next->prev = other->prev;
92  	list->next = other->next;
93  }
94  
95  WL_EXPORT void
wl_array_init(struct wl_array * array)96  wl_array_init(struct wl_array *array)
97  {
98  	memset(array, 0, sizeof *array);
99  }
100  
101  WL_EXPORT void
wl_array_release(struct wl_array * array)102  wl_array_release(struct wl_array *array)
103  {
104  	free(array->data);
105  	array->data = WL_ARRAY_POISON_PTR;
106  }
107  
108  WL_EXPORT void *
wl_array_add(struct wl_array * array,size_t size)109  wl_array_add(struct wl_array *array, size_t size)
110  {
111  	size_t alloc;
112  	void *data, *p;
113  
114  	if (array->alloc > 0)
115  		alloc = array->alloc;
116  	else
117  		alloc = 16;
118  
119  	while (alloc < array->size + size)
120  		alloc *= 2;
121  
122  	if (array->alloc < alloc) {
123  		if (array->alloc > 0)
124  			data = realloc(array->data, alloc);
125  		else
126  			data = malloc(alloc);
127  
128  		if (data == NULL)
129  			return NULL;
130  		array->data = data;
131  		array->alloc = alloc;
132  	}
133  
134  	p = array->data + array->size;
135  	array->size += size;
136  
137  	return p;
138  }
139  
140  WL_EXPORT int
wl_array_copy(struct wl_array * array,struct wl_array * source)141  wl_array_copy(struct wl_array *array, struct wl_array *source)
142  {
143  	if (array->size < source->size) {
144  		if (!wl_array_add(array, source->size - array->size))
145  			return -1;
146  	} else {
147  		array->size = source->size;
148  	}
149  
150  	memcpy(array->data, source->data, source->size);
151  	return 0;
152  }
153  
154  /** \cond */
155  
156  struct wl_object global_zombie_object;
157  
158  int
wl_interface_equal(const struct wl_interface * a,const struct wl_interface * b)159  wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b)
160  {
161  	/* In most cases the pointer equality test is sufficient.
162  	 * However, in some cases, depending on how things are split
163  	 * across shared objects, we can end up with multiple
164  	 * instances of the interface metadata constants.  So if the
165  	 * pointers match, the interfaces are equal, if they don't
166  	 * match we have to compare the interface names.
167  	 */
168  	return a == b || strcmp(a->name, b->name) == 0;
169  }
170  
171  union map_entry {
172  	uintptr_t next;
173  	void *data;
174  };
175  
176  #define map_entry_is_free(entry) ((entry).next & 0x1)
177  #define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
178  #define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
179  
180  WL_EXPORT void
wl_map_init(struct wl_map * map,uint32_t side)181  wl_map_init(struct wl_map *map, uint32_t side)
182  {
183  	memset(map, 0, sizeof *map);
184  	map->side = side;
185  }
186  
187  WL_EXPORT void
wl_map_release(struct wl_map * map)188  wl_map_release(struct wl_map *map)
189  {
190  	wl_array_release(&map->client_entries);
191  	wl_array_release(&map->server_entries);
192  }
193  
194  WL_EXPORT uint32_t
wl_map_insert_new(struct wl_map * map,uint32_t flags,void * data)195  wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
196  {
197  	union map_entry *start, *entry;
198  	struct wl_array *entries;
199  	uint32_t base;
200  
201  	if (map->side == WL_MAP_CLIENT_SIDE) {
202  		entries = &map->client_entries;
203  		base = 0;
204  	} else {
205  		entries = &map->server_entries;
206  		base = WL_SERVER_ID_START;
207  	}
208  
209  	if (map->free_list) {
210  		start = entries->data;
211  		entry = &start[map->free_list >> 1];
212  		map->free_list = entry->next;
213  	} else {
214  		entry = wl_array_add(entries, sizeof *entry);
215  		if (!entry)
216  			return 0;
217  		start = entries->data;
218  	}
219  
220  	entry->data = data;
221  	entry->next |= (flags & 0x1) << 1;
222  
223  	return (entry - start) + base;
224  }
225  
226  WL_EXPORT int
wl_map_insert_at(struct wl_map * map,uint32_t flags,uint32_t i,void * data)227  wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data)
228  {
229  	union map_entry *start;
230  	uint32_t count;
231  	struct wl_array *entries;
232  
233  	if (i < WL_SERVER_ID_START) {
234  		entries = &map->client_entries;
235  	} else {
236  		entries = &map->server_entries;
237  		i -= WL_SERVER_ID_START;
238  	}
239  
240  	count = entries->size / sizeof *start;
241  	if (count < i)
242  		return -1;
243  
244  	if (count == i)
245  		wl_array_add(entries, sizeof *start);
246  
247  	start = entries->data;
248  	start[i].data = data;
249  	start[i].next |= (flags & 0x1) << 1;
250  
251  	return 0;
252  }
253  
254  WL_EXPORT int
wl_map_reserve_new(struct wl_map * map,uint32_t i)255  wl_map_reserve_new(struct wl_map *map, uint32_t i)
256  {
257  	union map_entry *start;
258  	uint32_t count;
259  	struct wl_array *entries;
260  
261  	if (i < WL_SERVER_ID_START) {
262  		if (map->side == WL_MAP_CLIENT_SIDE)
263  			return -1;
264  
265  		entries = &map->client_entries;
266  	} else {
267  		if (map->side == WL_MAP_SERVER_SIDE)
268  			return -1;
269  
270  		entries = &map->server_entries;
271  		i -= WL_SERVER_ID_START;
272  	}
273  
274  	count = entries->size / sizeof *start;
275  
276  	if (count < i)
277  		return -1;
278  
279  	if (count == i) {
280  		wl_array_add(entries, sizeof *start);
281  		start = entries->data;
282  		start[i].data = NULL;
283  	} else {
284  		start = entries->data;
285  		if (start[i].data != NULL) {
286  			return -1;
287  		}
288  	}
289  
290  	return 0;
291  }
292  
293  WL_EXPORT void
wl_map_remove(struct wl_map * map,uint32_t i)294  wl_map_remove(struct wl_map *map, uint32_t i)
295  {
296  	union map_entry *start;
297  	struct wl_array *entries;
298  
299  	if (i < WL_SERVER_ID_START) {
300  		if (map->side == WL_MAP_SERVER_SIDE)
301  			return;
302  
303  		entries = &map->client_entries;
304  	} else {
305  		if (map->side == WL_MAP_CLIENT_SIDE)
306  			return;
307  
308  		entries = &map->server_entries;
309  		i -= WL_SERVER_ID_START;
310  	}
311  
312  	start = entries->data;
313  	start[i].next = map->free_list;
314  	map->free_list = (i << 1) | 1;
315  }
316  
317  WL_EXPORT void *
wl_map_lookup(struct wl_map * map,uint32_t i)318  wl_map_lookup(struct wl_map *map, uint32_t i)
319  {
320  	union map_entry *start;
321  	uint32_t count;
322  	struct wl_array *entries;
323  
324  	if (i < WL_SERVER_ID_START) {
325  		entries = &map->client_entries;
326  	} else {
327  		entries = &map->server_entries;
328  		i -= WL_SERVER_ID_START;
329  	}
330  
331  	start = entries->data;
332  	count = entries->size / sizeof *start;
333  
334  	if (i < count && !map_entry_is_free(start[i]))
335  		return map_entry_get_data(start[i]);
336  
337  	return NULL;
338  }
339  
340  WL_EXPORT uint32_t
wl_map_lookup_flags(struct wl_map * map,uint32_t i)341  wl_map_lookup_flags(struct wl_map *map, uint32_t i)
342  {
343  	union map_entry *start;
344  	uint32_t count;
345  	struct wl_array *entries;
346  
347  	if (i < WL_SERVER_ID_START) {
348  		entries = &map->client_entries;
349  	} else {
350  		entries = &map->server_entries;
351  		i -= WL_SERVER_ID_START;
352  	}
353  
354  	start = entries->data;
355  	count = entries->size / sizeof *start;
356  
357  	if (i < count && !map_entry_is_free(start[i]))
358  		return map_entry_get_flags(start[i]);
359  
360  	return 0;
361  }
362  
363  static enum wl_iterator_result
for_each_helper(struct wl_array * entries,wl_iterator_func_t func,void * data)364  for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
365  {
366  	union map_entry *start, *end, *p;
367  	enum wl_iterator_result ret = WL_ITERATOR_CONTINUE;
368  
369  	start = entries->data;
370  	end = (union map_entry *) ((char *) entries->data + entries->size);
371  
372  	for (p = start; p < end; p++)
373  		if (p->data && !map_entry_is_free(*p)) {
374  			ret = func(map_entry_get_data(*p), data);
375  			if (ret != WL_ITERATOR_CONTINUE)
376  				break;
377  		}
378  
379  	return ret;
380  }
381  
382  WL_EXPORT void
wl_map_for_each(struct wl_map * map,wl_iterator_func_t func,void * data)383  wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
384  {
385  	enum wl_iterator_result ret;
386  
387  	ret = for_each_helper(&map->client_entries, func, data);
388  	if (ret == WL_ITERATOR_CONTINUE)
389  		for_each_helper(&map->server_entries, func, data);
390  }
391  
392  static void
wl_log_stderr_handler(const char * fmt,va_list arg)393  wl_log_stderr_handler(const char *fmt, va_list arg)
394  {
395  	vfprintf(stderr, fmt, arg);
396  }
397  
398  wl_log_func_t wl_log_handler = wl_log_stderr_handler;
399  
400  void
wl_log(const char * fmt,...)401  wl_log(const char *fmt, ...)
402  {
403  	va_list argp;
404  
405  	va_start(argp, fmt);
406  	wl_log_handler(fmt, argp);
407  	va_end(argp);
408  }
409  
410  void
wl_abort(const char * fmt,...)411  wl_abort(const char *fmt, ...)
412  {
413  	va_list argp;
414  
415  	va_start(argp, fmt);
416  	wl_log_handler(fmt, argp);
417  	va_end(argp);
418  
419  	abort();
420  }
421  
422  /** \endcond */
423