-
Notifications
You must be signed in to change notification settings - Fork 0
/
dynarray.c
123 lines (102 loc) · 2.79 KB
/
dynarray.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <stdlib.h>
#include <string.h>
#include "dynarray.h"
#include "util.h"
#include <stdio.h>
//
// WARNING!
// some bugs with resize may exist!
//
static const size_t ALLOC_STEP = 64;
dynarray_t* dynarray_create(void)
{
dynarray_t* arr = malloc(sizeof(dynarray_t));
arr->_arr = NULL;
arr->_capacity = 0;
arr->len = 0;
return arr;
}
void dynarray_free(dynarray_t** arr)
{
free((*arr)->_arr);
free(*arr);
arr = NULL;
}
static void _assert_index(dynarray_t* arr, size_t index)
{
if (index > arr->_capacity - 1 || index < 0) {
die("dynarray: index %d out of bounds (capacity=%d)", index, arr->_capacity);
}
}
static void _grow_if_needed(dynarray_t* arr)
{
if (arr->len + 1 > arr->_capacity) {
size_t old_size = arr->_capacity;
arr->_capacity += ALLOC_STEP;
arr->_arr = realloc(arr->_arr, sizeof(void*) * arr->_capacity);
if (arr->_arr == NULL) {
die("dynarray: couldn't reallocate memory");
}
memset(arr->_arr + old_size, 0, sizeof(void*) * ALLOC_STEP); // important for sparse arrays
}
}
// Returns
// - NULL if value did not replace another one
// - void* to a previous value if replaced
void* dynarray_set(dynarray_t* arr, size_t index, void* value)
{
_grow_if_needed(arr);
void* old_value_ptr = dynarray_get(arr, index);
arr->_arr[index] = value;
arr->len = index > arr->len ? index + 1: arr->len + 1; // when array is sparse
return old_value_ptr;
}
void* dynarray_get(dynarray_t* arr, size_t index)
{
_assert_index(arr, index);
return arr->_arr[index];
}
// Cuts the value at index from array1
// Returns a pointer to the deleted item (may be void*)
void* dynarray_cut(dynarray_t* arr, size_t index)
{
void *old_value_ptr = dynarray_get(arr, index);
// index = 1, len = 5
// {1, 2, 3, 4, 5} => // {1, 3, 4, 5}
size_t move_items = arr->len - index; // should be -1 but +1 item is to ensure zeroing
memmove(
arr->_arr + index * sizeof(void*),
arr->_arr + index * sizeof(void*) + 1,
move_items * sizeof(void*)
);
arr->len = arr->len - 1;
return old_value_ptr;
}
void dynarray_append(dynarray_t* arr, void* value)
{
dynarray_set(arr, arr->len, value);
}
void* dynarray_get_top(dynarray_t* arr)
{
return dynarray_get(arr, arr->len - 1);
}
void* dynarray_remove_top(dynarray_t* arr)
{
if (arr->len == 0) {
die("dynarray: length is 0, nothing to pop");
}
void* value_ptr = arr->_arr[arr->len - 1];
arr->_arr[arr->len - 1] = NULL;
arr->len--;
return value_ptr;
}
void DEBUG_dynarray_dump(dynarray_t* arr)
{
printf("\ndynarray stats:\n");
printf("address = %p\n", (void*) arr);
printf("len = %d, capacity = %d, _arr (addr) = %p\n", (int) arr->len, (int) arr->_capacity, (void*) arr->_arr);
for (size_t i = 0; i < arr->len; i++) {
printf("arr[%zu] = %p\n", i, dynarray_get(arr, i));
}
printf("\n");
}