u_dynarray.h revision 8a1362ad
101e04c3fSmrg/************************************************************************** 201e04c3fSmrg * 301e04c3fSmrg * Copyright 2010 Luca Barbieri 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining 601e04c3fSmrg * a copy of this software and associated documentation files (the 701e04c3fSmrg * "Software"), to deal in the Software without restriction, including 801e04c3fSmrg * without limitation the rights to use, copy, modify, merge, publish, 901e04c3fSmrg * distribute, sublicense, and/or sell copies of the Software, and to 1001e04c3fSmrg * permit persons to whom the Software is furnished to do so, subject to 1101e04c3fSmrg * the following conditions: 1201e04c3fSmrg * 1301e04c3fSmrg * The above copyright notice and this permission notice (including the 1401e04c3fSmrg * next paragraph) shall be included in all copies or substantial 1501e04c3fSmrg * portions of the Software. 1601e04c3fSmrg * 1701e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1801e04c3fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1901e04c3fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2001e04c3fSmrg * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 2101e04c3fSmrg * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2201e04c3fSmrg * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2301e04c3fSmrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2401e04c3fSmrg * 2501e04c3fSmrg **************************************************************************/ 2601e04c3fSmrg 2701e04c3fSmrg#ifndef U_DYNARRAY_H 2801e04c3fSmrg#define U_DYNARRAY_H 2901e04c3fSmrg 3001e04c3fSmrg#include <stdlib.h> 3101e04c3fSmrg#include <string.h> 3201e04c3fSmrg#include "ralloc.h" 3301e04c3fSmrg 3401e04c3fSmrg#ifdef __cplusplus 3501e04c3fSmrgextern "C" { 3601e04c3fSmrg#endif 3701e04c3fSmrg 3801e04c3fSmrg/* A zero-initialized version of this is guaranteed to represent an 3901e04c3fSmrg * empty array. 4001e04c3fSmrg * 4101e04c3fSmrg * Also, size <= capacity and data != 0 if and only if capacity != 0 4201e04c3fSmrg * capacity will always be the allocation size of data 4301e04c3fSmrg */ 4401e04c3fSmrgstruct util_dynarray 4501e04c3fSmrg{ 4601e04c3fSmrg void *mem_ctx; 4701e04c3fSmrg void *data; 4801e04c3fSmrg unsigned size; 4901e04c3fSmrg unsigned capacity; 5001e04c3fSmrg}; 5101e04c3fSmrg 5201e04c3fSmrgstatic inline void 5301e04c3fSmrgutil_dynarray_init(struct util_dynarray *buf, void *mem_ctx) 5401e04c3fSmrg{ 5501e04c3fSmrg memset(buf, 0, sizeof(*buf)); 5601e04c3fSmrg buf->mem_ctx = mem_ctx; 5701e04c3fSmrg} 5801e04c3fSmrg 5901e04c3fSmrgstatic inline void 6001e04c3fSmrgutil_dynarray_fini(struct util_dynarray *buf) 6101e04c3fSmrg{ 6201e04c3fSmrg if (buf->data) { 6301e04c3fSmrg if (buf->mem_ctx) { 6401e04c3fSmrg ralloc_free(buf->data); 6501e04c3fSmrg } else { 6601e04c3fSmrg free(buf->data); 6701e04c3fSmrg } 6801e04c3fSmrg util_dynarray_init(buf, buf->mem_ctx); 6901e04c3fSmrg } 7001e04c3fSmrg} 7101e04c3fSmrg 7201e04c3fSmrgstatic inline void 7301e04c3fSmrgutil_dynarray_clear(struct util_dynarray *buf) 7401e04c3fSmrg{ 7501e04c3fSmrg buf->size = 0; 7601e04c3fSmrg} 7701e04c3fSmrg 7801e04c3fSmrg#define DYN_ARRAY_INITIAL_SIZE 64 7901e04c3fSmrg 8001e04c3fSmrgstatic inline void * 818a1362adSmayautil_dynarray_ensure_cap(struct util_dynarray *buf, unsigned newcap) 8201e04c3fSmrg{ 838a1362adSmaya if (newcap > buf->capacity) { 8401e04c3fSmrg if (buf->capacity == 0) 8501e04c3fSmrg buf->capacity = DYN_ARRAY_INITIAL_SIZE; 8601e04c3fSmrg 878a1362adSmaya while (newcap > buf->capacity) 8801e04c3fSmrg buf->capacity *= 2; 8901e04c3fSmrg 9001e04c3fSmrg if (buf->mem_ctx) { 9101e04c3fSmrg buf->data = reralloc_size(buf->mem_ctx, buf->data, buf->capacity); 9201e04c3fSmrg } else { 9301e04c3fSmrg buf->data = realloc(buf->data, buf->capacity); 9401e04c3fSmrg } 9501e04c3fSmrg } 9601e04c3fSmrg 978a1362adSmaya return (void *)((char *)buf->data + buf->size); 988a1362adSmaya} 998a1362adSmaya 1008a1362adSmayastatic inline void * 1018a1362adSmayautil_dynarray_grow_cap(struct util_dynarray *buf, int diff) 1028a1362adSmaya{ 1038a1362adSmaya return util_dynarray_ensure_cap(buf, buf->size + diff); 1048a1362adSmaya} 1058a1362adSmaya 1068a1362adSmaya/* use util_dynarray_trim to reduce the allocated storage */ 1078a1362adSmayastatic inline void * 1088a1362adSmayautil_dynarray_resize(struct util_dynarray *buf, unsigned newsize) 1098a1362adSmaya{ 1108a1362adSmaya void *p = util_dynarray_ensure_cap(buf, newsize); 11101e04c3fSmrg buf->size = newsize; 11201e04c3fSmrg 11301e04c3fSmrg return p; 11401e04c3fSmrg} 11501e04c3fSmrg 11601e04c3fSmrgstatic inline void 11701e04c3fSmrgutil_dynarray_clone(struct util_dynarray *buf, void *mem_ctx, 11801e04c3fSmrg struct util_dynarray *from_buf) 11901e04c3fSmrg{ 12001e04c3fSmrg util_dynarray_init(buf, mem_ctx); 12101e04c3fSmrg util_dynarray_resize(buf, from_buf->size); 12201e04c3fSmrg memcpy(buf->data, from_buf->data, from_buf->size); 12301e04c3fSmrg} 12401e04c3fSmrg 12501e04c3fSmrgstatic inline void * 12601e04c3fSmrgutil_dynarray_grow(struct util_dynarray *buf, int diff) 12701e04c3fSmrg{ 12801e04c3fSmrg return util_dynarray_resize(buf, buf->size + diff); 12901e04c3fSmrg} 13001e04c3fSmrg 13101e04c3fSmrgstatic inline void 13201e04c3fSmrgutil_dynarray_trim(struct util_dynarray *buf) 13301e04c3fSmrg{ 13401e04c3fSmrg if (buf->size != buf->capacity) { 13501e04c3fSmrg if (buf->size) { 13601e04c3fSmrg if (buf->mem_ctx) { 13701e04c3fSmrg buf->data = reralloc_size(buf->mem_ctx, buf->data, buf->size); 13801e04c3fSmrg } else { 13901e04c3fSmrg buf->data = realloc(buf->data, buf->size); 14001e04c3fSmrg } 14101e04c3fSmrg buf->capacity = buf->size; 14201e04c3fSmrg } else { 14301e04c3fSmrg if (buf->mem_ctx) { 14401e04c3fSmrg ralloc_free(buf->data); 14501e04c3fSmrg } else { 14601e04c3fSmrg free(buf->data); 14701e04c3fSmrg } 14801e04c3fSmrg buf->data = NULL; 14901e04c3fSmrg buf->capacity = 0; 15001e04c3fSmrg } 15101e04c3fSmrg } 15201e04c3fSmrg} 15301e04c3fSmrg 15401e04c3fSmrg#define util_dynarray_append(buf, type, v) do {type __v = (v); memcpy(util_dynarray_grow((buf), sizeof(type)), &__v, sizeof(type));} while(0) 15501e04c3fSmrg#define util_dynarray_top_ptr(buf, type) (type*)((char*)(buf)->data + (buf)->size - sizeof(type)) 15601e04c3fSmrg#define util_dynarray_top(buf, type) *util_dynarray_top_ptr(buf, type) 15701e04c3fSmrg#define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type))) 15801e04c3fSmrg#define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type) 15901e04c3fSmrg#define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type)) 16001e04c3fSmrg#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx)) 16101e04c3fSmrg#define util_dynarray_begin(buf) ((buf)->data) 16201e04c3fSmrg#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size)) 16301e04c3fSmrg#define util_dynarray_num_elements(buf, type) ((buf)->size / sizeof(type)) 16401e04c3fSmrg 16501e04c3fSmrg#define util_dynarray_foreach(buf, type, elem) \ 16601e04c3fSmrg for (type *elem = (type *)(buf)->data; \ 16701e04c3fSmrg elem < (type *)((char *)(buf)->data + (buf)->size); elem++) 16801e04c3fSmrg 16901e04c3fSmrg#define util_dynarray_foreach_reverse(buf, type, elem) \ 17001e04c3fSmrg if ((buf)->size > 0) \ 17101e04c3fSmrg for (type *elem = util_dynarray_top_ptr(buf, type); \ 17201e04c3fSmrg elem; \ 17301e04c3fSmrg elem = elem > (type *)(buf)->data ? elem - 1 : NULL) 17401e04c3fSmrg 17501e04c3fSmrg#define util_dynarray_delete_unordered(buf, type, v) \ 17601e04c3fSmrg do { \ 17701e04c3fSmrg unsigned num_elements = (buf)->size / sizeof(type); \ 17801e04c3fSmrg unsigned i; \ 17901e04c3fSmrg for (i = 0; i < num_elements; i++) { \ 18001e04c3fSmrg type __v = *util_dynarray_element((buf), type, (i)); \ 18101e04c3fSmrg if (v == __v) { \ 18201e04c3fSmrg memcpy(util_dynarray_element((buf), type, (i)), \ 18301e04c3fSmrg util_dynarray_pop_ptr((buf), type), sizeof(type)); \ 18401e04c3fSmrg break; \ 18501e04c3fSmrg } \ 18601e04c3fSmrg } \ 18701e04c3fSmrg } while (0) 18801e04c3fSmrg 18901e04c3fSmrg#ifdef __cplusplus 19001e04c3fSmrg} 19101e04c3fSmrg#endif 19201e04c3fSmrg 19301e04c3fSmrg#endif /* U_DYNARRAY_H */ 19401e04c3fSmrg 195