Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2008-2011 Kristian Hgsberg
      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
     37 wl_list_init(struct wl_list *list)
     38 {
     39 	list->prev = list;
     40 	list->next = list;
     41 }
     42 
     43 WL_EXPORT void
     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
     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
     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
     78 wl_list_empty(const struct wl_list *list)
     79 {
     80 	return list->next == list;
     81 }
     82 
     83 WL_EXPORT void
     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
     96 wl_array_init(struct wl_array *array)
     97 {
     98 	memset(array, 0, sizeof *array);
     99 }
    100 
    101 WL_EXPORT void
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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