naev 0.11.5
intlist.c
1/*
2 * This code was initially authored by the Stackoverflow user dragon-energy and posted under following page:
3 * https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det
4 *
5 * As for the license, the author has kindly noted:
6 *
7 * "Oh and feel free to use this code I post however you want, even for commercial projects.
8 * I would really love it if people let me know if they find it useful, but do as you wish."
9 *
10 * And generally all Stackoverflow-posted code is by default licensed with CC BY-SA 4.0:
11 * https://creativecommons.org/licenses/by-sa/4.0/
12 */
13#include "intlist.h"
14#include <stdlib.h>
15#include <string.h>
16#include <assert.h>
17
18void il_create(IntList* il, int num_fields)
19{
20 il->data = il->fixed;
21 il->num = 0;
22 il->cap = il_fixed_cap;
23 il->num_fields = num_fields;
24 il->free_element = -1;
25}
26
27void il_destroy(IntList* il)
28{
29 // Free the buffer only if it was heap allocated.
30 if (il->data != il->fixed)
31 free(il->data);
32}
33
34void il_clear(IntList* il)
35{
36 il->num = 0;
37 il->free_element = -1;
38}
39
40int il_size(const IntList* il)
41{
42 return il->num;
43}
44
45int il_get(const IntList* il, int n, int field)
46{
47 assert(n >= 0 && n < il->num);
48 return il->data[n*il->num_fields + field];
49}
50
51void il_set(IntList* il, int n, int field, int val)
52{
53 assert(n >= 0 && n < il->num);
54 il->data[n*il->num_fields + field] = val;
55}
56
57int il_push_back(IntList* il)
58{
59 const int new_pos = (il->num+1) * il->num_fields;
60
61 // If the list is full, we need to reallocate the buffer to make room
62 // for the new element.
63 if (new_pos > il->cap)
64 {
65 // Use double the size for the new capacity.
66 const int new_cap = new_pos * 2;
67
68 // If we're pointing to the fixed buffer, allocate a new array on the
69 // heap and copy the fixed buffer contents to it.
70 if (il->cap == il_fixed_cap)
71 {
72 il->data = malloc(new_cap * sizeof(*il->data));
73 memcpy(il->data, il->fixed, sizeof(il->fixed));
74 }
75 else
76 {
77 // Otherwise reallocate the heap buffer to the new size.
78 il->data = realloc(il->data, new_cap * sizeof(*il->data));
79 }
80 // Set the old capacity to the new capacity.
81 il->cap = new_cap;
82 }
83 return il->num++;
84}
85
86void il_pop_back(IntList* il)
87{
88 // Just decrement the list size.
89 assert(il->num > 0);
90 --il->num;
91}
92
93int il_insert(IntList* il)
94{
95 // If there's a free index in the free list, pop that and use it.
96 if (il->free_element != -1)
97 {
98 const int index = il->free_element;
99 const int pos = index * il->num_fields;
100
101 // Set the free index to the next free index.
102 il->free_element = il->data[pos];
103
104 // Return the free index.
105 return index;
106 }
107 // Otherwise insert to the back of the array.
108 return il_push_back(il);
109}
110
111void il_erase(IntList* il, int n)
112{
113 // Push the element to the free list.
114 const int pos = n * il->num_fields;
115 il->data[pos] = il->free_element;
116 il->free_element = n;
117}