1b8e80941Smrg/************************************************************************** 2b8e80941Smrg * 3b8e80941Smrg * Copyright 2010 Luca Barbieri 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining 6b8e80941Smrg * a copy of this software and associated documentation files (the 7b8e80941Smrg * "Software"), to deal in the Software without restriction, including 8b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish, 9b8e80941Smrg * distribute, sublicense, and/or sell copies of the Software, and to 10b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to 11b8e80941Smrg * the following conditions: 12b8e80941Smrg * 13b8e80941Smrg * The above copyright notice and this permission notice (including the 14b8e80941Smrg * next paragraph) shall be included in all copies or substantial 15b8e80941Smrg * portions of the Software. 16b8e80941Smrg * 17b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18b8e80941Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20b8e80941Smrg * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21b8e80941Smrg * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22b8e80941Smrg * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23b8e80941Smrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24b8e80941Smrg * 25b8e80941Smrg **************************************************************************/ 26b8e80941Smrg 27b8e80941Smrg#ifndef U_DYNARRAY_H 28b8e80941Smrg#define U_DYNARRAY_H 29b8e80941Smrg 30b8e80941Smrg#include <stdlib.h> 31b8e80941Smrg#include <string.h> 32b8e80941Smrg#include "ralloc.h" 33b8e80941Smrg 34b8e80941Smrg#ifdef __cplusplus 35b8e80941Smrgextern "C" { 36b8e80941Smrg#endif 37b8e80941Smrg 38b8e80941Smrg/* A zero-initialized version of this is guaranteed to represent an 39b8e80941Smrg * empty array. 40b8e80941Smrg * 41b8e80941Smrg * Also, size <= capacity and data != 0 if and only if capacity != 0 42b8e80941Smrg * capacity will always be the allocation size of data 43b8e80941Smrg */ 44b8e80941Smrgstruct util_dynarray 45b8e80941Smrg{ 46b8e80941Smrg void *mem_ctx; 47b8e80941Smrg void *data; 48b8e80941Smrg unsigned size; 49b8e80941Smrg unsigned capacity; 50b8e80941Smrg}; 51b8e80941Smrg 52b8e80941Smrgstatic inline void 53b8e80941Smrgutil_dynarray_init(struct util_dynarray *buf, void *mem_ctx) 54b8e80941Smrg{ 55b8e80941Smrg memset(buf, 0, sizeof(*buf)); 56b8e80941Smrg buf->mem_ctx = mem_ctx; 57b8e80941Smrg} 58b8e80941Smrg 59b8e80941Smrgstatic inline void 60b8e80941Smrgutil_dynarray_fini(struct util_dynarray *buf) 61b8e80941Smrg{ 62b8e80941Smrg if (buf->data) { 63b8e80941Smrg if (buf->mem_ctx) { 64b8e80941Smrg ralloc_free(buf->data); 65b8e80941Smrg } else { 66b8e80941Smrg free(buf->data); 67b8e80941Smrg } 68b8e80941Smrg util_dynarray_init(buf, buf->mem_ctx); 69b8e80941Smrg } 70b8e80941Smrg} 71b8e80941Smrg 72b8e80941Smrgstatic inline void 73b8e80941Smrgutil_dynarray_clear(struct util_dynarray *buf) 74b8e80941Smrg{ 75b8e80941Smrg buf->size = 0; 76b8e80941Smrg} 77b8e80941Smrg 78b8e80941Smrg#define DYN_ARRAY_INITIAL_SIZE 64 79b8e80941Smrg 80b8e80941Smrgstatic inline void * 81b8e80941Smrgutil_dynarray_ensure_cap(struct util_dynarray *buf, unsigned newcap) 82b8e80941Smrg{ 83b8e80941Smrg if (newcap > buf->capacity) { 84b8e80941Smrg if (buf->capacity == 0) 85b8e80941Smrg buf->capacity = DYN_ARRAY_INITIAL_SIZE; 86b8e80941Smrg 87b8e80941Smrg while (newcap > buf->capacity) 88b8e80941Smrg buf->capacity *= 2; 89b8e80941Smrg 90b8e80941Smrg if (buf->mem_ctx) { 91b8e80941Smrg buf->data = reralloc_size(buf->mem_ctx, buf->data, buf->capacity); 92b8e80941Smrg } else { 93b8e80941Smrg buf->data = realloc(buf->data, buf->capacity); 94b8e80941Smrg } 95b8e80941Smrg } 96b8e80941Smrg 97b8e80941Smrg return (void *)((char *)buf->data + buf->size); 98b8e80941Smrg} 99b8e80941Smrg 100b8e80941Smrgstatic inline void * 101b8e80941Smrgutil_dynarray_grow_cap(struct util_dynarray *buf, int diff) 102b8e80941Smrg{ 103b8e80941Smrg return util_dynarray_ensure_cap(buf, buf->size + diff); 104b8e80941Smrg} 105b8e80941Smrg 106b8e80941Smrg/* use util_dynarray_trim to reduce the allocated storage */ 107b8e80941Smrgstatic inline void * 108b8e80941Smrgutil_dynarray_resize(struct util_dynarray *buf, unsigned newsize) 109b8e80941Smrg{ 110b8e80941Smrg void *p = util_dynarray_ensure_cap(buf, newsize); 111b8e80941Smrg buf->size = newsize; 112b8e80941Smrg 113b8e80941Smrg return p; 114b8e80941Smrg} 115b8e80941Smrg 116b8e80941Smrgstatic inline void 117b8e80941Smrgutil_dynarray_clone(struct util_dynarray *buf, void *mem_ctx, 118b8e80941Smrg struct util_dynarray *from_buf) 119b8e80941Smrg{ 120b8e80941Smrg util_dynarray_init(buf, mem_ctx); 121b8e80941Smrg util_dynarray_resize(buf, from_buf->size); 122b8e80941Smrg memcpy(buf->data, from_buf->data, from_buf->size); 123b8e80941Smrg} 124b8e80941Smrg 125b8e80941Smrgstatic inline void * 126b8e80941Smrgutil_dynarray_grow(struct util_dynarray *buf, int diff) 127b8e80941Smrg{ 128b8e80941Smrg return util_dynarray_resize(buf, buf->size + diff); 129b8e80941Smrg} 130b8e80941Smrg 131b8e80941Smrgstatic inline void 132b8e80941Smrgutil_dynarray_trim(struct util_dynarray *buf) 133b8e80941Smrg{ 134b8e80941Smrg if (buf->size != buf->capacity) { 135b8e80941Smrg if (buf->size) { 136b8e80941Smrg if (buf->mem_ctx) { 137b8e80941Smrg buf->data = reralloc_size(buf->mem_ctx, buf->data, buf->size); 138b8e80941Smrg } else { 139b8e80941Smrg buf->data = realloc(buf->data, buf->size); 140b8e80941Smrg } 141b8e80941Smrg buf->capacity = buf->size; 142b8e80941Smrg } else { 143b8e80941Smrg if (buf->mem_ctx) { 144b8e80941Smrg ralloc_free(buf->data); 145b8e80941Smrg } else { 146b8e80941Smrg free(buf->data); 147b8e80941Smrg } 148b8e80941Smrg buf->data = NULL; 149b8e80941Smrg buf->capacity = 0; 150b8e80941Smrg } 151b8e80941Smrg } 152b8e80941Smrg} 153b8e80941Smrg 154b8e80941Smrg#define util_dynarray_append(buf, type, v) do {type __v = (v); memcpy(util_dynarray_grow((buf), sizeof(type)), &__v, sizeof(type));} while(0) 155b8e80941Smrg#define util_dynarray_top_ptr(buf, type) (type*)((char*)(buf)->data + (buf)->size - sizeof(type)) 156b8e80941Smrg#define util_dynarray_top(buf, type) *util_dynarray_top_ptr(buf, type) 157b8e80941Smrg#define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type))) 158b8e80941Smrg#define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type) 159b8e80941Smrg#define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type)) 160b8e80941Smrg#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx)) 161b8e80941Smrg#define util_dynarray_begin(buf) ((buf)->data) 162b8e80941Smrg#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size)) 163b8e80941Smrg#define util_dynarray_num_elements(buf, type) ((buf)->size / sizeof(type)) 164b8e80941Smrg 165b8e80941Smrg#define util_dynarray_foreach(buf, type, elem) \ 166b8e80941Smrg for (type *elem = (type *)(buf)->data; \ 167b8e80941Smrg elem < (type *)((char *)(buf)->data + (buf)->size); elem++) 168b8e80941Smrg 169b8e80941Smrg#define util_dynarray_foreach_reverse(buf, type, elem) \ 170b8e80941Smrg if ((buf)->size > 0) \ 171b8e80941Smrg for (type *elem = util_dynarray_top_ptr(buf, type); \ 172b8e80941Smrg elem; \ 173b8e80941Smrg elem = elem > (type *)(buf)->data ? elem - 1 : NULL) 174b8e80941Smrg 175b8e80941Smrg#define util_dynarray_delete_unordered(buf, type, v) \ 176b8e80941Smrg do { \ 177b8e80941Smrg unsigned num_elements = (buf)->size / sizeof(type); \ 178b8e80941Smrg unsigned i; \ 179b8e80941Smrg for (i = 0; i < num_elements; i++) { \ 180b8e80941Smrg type __v = *util_dynarray_element((buf), type, (i)); \ 181b8e80941Smrg if (v == __v) { \ 182b8e80941Smrg memcpy(util_dynarray_element((buf), type, (i)), \ 183b8e80941Smrg util_dynarray_pop_ptr((buf), type), sizeof(type)); \ 184b8e80941Smrg break; \ 185b8e80941Smrg } \ 186b8e80941Smrg } \ 187b8e80941Smrg } while (0) 188b8e80941Smrg 189b8e80941Smrg#ifdef __cplusplus 190b8e80941Smrg} 191b8e80941Smrg#endif 192b8e80941Smrg 193b8e80941Smrg#endif /* U_DYNARRAY_H */ 194b8e80941Smrg 195