20 #ifndef SRC_PARSING_MEMORY_POOL_H 21 #define SRC_PARSING_MEMORY_POOL_H 74 #define IMPLEMENT_DEQUE_MEMORY_POOL(struct_name, type) \ 76 void apply_##struct_name(struct_name*, void (*)(type)); \ 78 struct_name new_##struct_name(size_t init_cap) { \ 86 ret.data = (type*) memory_pool_alloc(ret.cap * sizeof(type)); \ 88 if (ret.data == NULL) { \ 89 fprintf(stderr, "ERROR: Failed to reallocate struct_name" \ 94 ret.front = ret.back = 0; \ 95 ret.destructor = NULL; \ 100 struct_name new_destructable_##struct_name(size_t init_cap, \ 101 void (*destructor)(type)){ \ 102 struct_name ret = new_##struct_name(init_cap); \ 103 ret.destructor = destructor; \ 107 void destroy_##struct_name(struct_name* deq) { \ 108 assert(deq != NULL); \ 110 if (deq->data == NULL) \ 113 if (deq->destructor != NULL) \ 114 apply_##struct_name(deq, deq->destructor); \ 118 deq->front = deq->back = 0; \ 121 void empty_##struct_name(struct_name* deq) { \ 122 assert(deq != NULL); \ 123 assert(deq->data != NULL); \ 125 if (deq->destructor != NULL) \ 126 apply_##struct_name(deq, deq->destructor); \ 128 deq->front = deq->back = 0; \ 131 bool is_empty_##struct_name(struct_name* deq) { \ 132 assert(deq != NULL); \ 133 assert(deq->data != NULL); \ 134 return deq->front == deq->back; \ 137 size_t length_##struct_name(struct_name* deq) { \ 138 assert(deq != NULL); \ 139 assert(deq->data != NULL); \ 140 return (deq->back - deq->front + deq->cap) % deq->cap; \ 143 static void __reallign_##struct_name(struct_name* deq) { \ 144 assert(deq != NULL); \ 145 assert(deq->data != NULL); \ 147 if (deq->front != 0) { \ 148 type* old_data = deq->data; \ 149 size_t len = length_##struct_name(deq); \ 151 deq->data = (type*) memory_pool_alloc(deq->cap * sizeof(type)); \ 153 if (deq->data == NULL) { \ 154 fprintf(stderr, "ERROR: Failed to reallocate struct_name" \ 161 for (i = 0; i < len; ++i) \ 162 deq->data[i] = old_data[(deq->front + i) % deq->cap]; \ 169 type* as_array_##struct_name(struct_name* deq, size_t* len) { \ 170 assert(deq != NULL); \ 171 assert(deq->data != NULL); \ 173 __reallign_##struct_name(deq); \ 175 type* ret = deq->data; \ 178 *len = length_##struct_name(deq); \ 181 deq->cap = deq->front = deq->back = 0; \ 186 void apply_##struct_name(struct_name* deq, void (*func)(type)) { \ 187 assert(deq != NULL); \ 188 assert(deq->data != NULL); \ 190 size_t len = length_##struct_name(deq); \ 192 for (size_t i = 0; i < len; ++i) { \ 193 func(deq->data[(deq->front + i) % deq->cap]); \ 197 static void __on_push_##struct_name(struct_name* deq) { \ 198 if (deq->front == (deq->back + 1) % deq->cap) { \ 199 type* old_data = deq->data; \ 200 size_t old_cap = deq->cap; \ 202 deq->cap = 2 * deq->cap; \ 203 deq->data = (type*) memory_pool_alloc(deq->cap * sizeof(type)); \ 205 if (deq->data == NULL) { \ 206 fprintf(stderr, "ERROR: Failed to reallocate struct_name" \ 213 for (i = 0; i < old_cap - 1; ++i) \ 214 deq->data[i] = old_data[(deq->front + i) % old_cap]; \ 221 static void __on_pop_##struct_name(struct_name* deq) { \ 222 if (is_empty_##struct_name(deq)) { \ 223 fprintf(stderr, "ERROR: Cannot pop from of struct_name while it " \ 229 void push_front_##struct_name(struct_name* deq, type element) { \ 230 assert(deq != NULL); \ 231 assert(deq->data != NULL); \ 232 __on_push_##struct_name(deq); \ 233 deq->front = (deq->front + deq->cap - 1) % deq->cap; \ 234 deq->data[deq->front] = element; \ 237 void push_back_##struct_name(struct_name* deq, type element) { \ 238 assert(deq != NULL); \ 239 assert(deq->data != NULL); \ 240 __on_push_##struct_name(deq); \ 241 deq->data[deq->back] = element; \ 242 deq->back = (deq->back + 1) % deq->cap; \ 245 type pop_front_##struct_name(struct_name* deq) { \ 246 assert(deq != NULL); \ 247 assert(deq->data != NULL); \ 248 __on_pop_##struct_name(deq); \ 249 size_t old_front = deq->front; \ 250 deq->front = (deq->front + 1) % deq->cap; \ 251 return deq->data[old_front]; \ 254 type pop_back_##struct_name(struct_name* deq) { \ 255 assert(deq != NULL); \ 256 assert(deq->data != NULL); \ 257 __on_pop_##struct_name(deq); \ 258 deq->back = (deq->back + deq->cap - 1) % deq->cap; \ 259 return deq->data[deq->back]; \ 262 type peek_front_##struct_name(struct_name* deq) { \ 263 assert(deq != NULL); \ 264 assert(deq->data != NULL); \ 265 assert(!is_empty_##struct_name(deq)); \ 266 return deq->data[deq->front]; \ 269 type peek_back_##struct_name(struct_name* deq) { \ 270 assert(deq != NULL); \ 271 assert(deq->data != NULL); \ 272 assert(!is_empty_##struct_name(deq)); \ 273 return deq->data[(deq->back + deq->cap - 1) % deq->cap]; \ 276 void update_front_##struct_name(struct_name* deq, type element) { \ 277 assert(deq != NULL); \ 278 assert(deq->data != NULL); \ 279 assert(!is_empty_##struct_name(deq)); \ 280 deq->data[deq->front] = element; \ 283 void update_back_##struct_name(struct_name* deq, type element) { \ 284 assert(deq != NULL); \ 285 assert(deq->data != NULL); \ 286 assert(!is_empty_##struct_name(deq)); \ 287 deq->data[(deq->back + deq->cap - 1) % deq->cap] = element; \ 290 void update_and_destroy_front_##struct_name(struct_name* deq, \ 292 assert(deq != NULL); \ 293 assert(deq->data != NULL); \ 294 assert(!is_empty_##struct_name(deq)); \ 296 size_t idx = deq->front; \ 298 if (deq->destructor != NULL) \ 299 deq->destructor(deq->data[idx]); \ 301 deq->data[idx] = element; \ 304 void update_and_destroy_back_##struct_name(struct_name* deq, \ 306 assert(deq != NULL); \ 307 assert(deq->data != NULL); \ 308 assert(!is_empty_##struct_name(deq)); \ 310 size_t idx = (deq->back + deq->cap - 1) % deq->cap; \ 312 if (deq->destructor != NULL) \ 313 deq->destructor(deq->data[idx]); \ 315 deq->data[idx] = element; \ void initialize_memory_pool(size_t size)
Allocate the memory pool.
Definition: memory_pool.c:83
void destroy_memory_pool()
Free all memory allocated in the memory pool.
Definition: memory_pool.c:143
Double ended queue generators specialized to any given type.
char * memory_pool_strdup(const char *str)
A version of strdup() that allocates the duplicate to the memory pool rather than with malloc directl...
Definition: memory_pool.c:148
void * memory_pool_alloc(size_t size)
Reserve some space in the memory pool and returns a unique address that can be written to and read fr...
Definition: memory_pool.c:98