aboutsummaryrefslogtreecommitdiff
path: root/deque.c
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2020-08-20 09:43:59 +0200
committerThomas Schmucker <ts@its1.de>2020-08-20 09:43:59 +0200
commitfa75450d127d745542f863077f141ea0c5cfe975 (patch)
tree87dcbceb2268a0a7c136221d043b6da69146fddb /deque.c
parentf6f15c219312f7f3a9d6d850861bafa6b4e9613a (diff)
downloaddata-structures-fa75450d127d745542f863077f141ea0c5cfe975.tar.gz
data-structures-fa75450d127d745542f863077f141ea0c5cfe975.tar.bz2
data-structures-fa75450d127d745542f863077f141ea0c5cfe975.zip
Eine einfache Fehlerbehandlung hinzugefügt. Von produktionsreifem Code sind wir allerdings noch weit entfernt!
Diffstat (limited to 'deque.c')
-rw-r--r--deque.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/deque.c b/deque.c
index 91c7a50..c4b1795 100644
--- a/deque.c
+++ b/deque.c
@@ -3,6 +3,8 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5 5
6#include "util.h"
7
6typedef int T; 8typedef int T;
7 9
8#define START_MAP_CAPACITY 4 10#define START_MAP_CAPACITY 4
@@ -19,16 +21,28 @@ struct deque {
19 size_t size; 21 size_t size;
20}; 22};
21 23
24static void *
25allocate(size_t n, size_t sz)
26{
27 void *ptr = calloc(n, sz);
28 if ( ptr == NULL ) {
29 ERROR("out of memory!");
30 }
31 return ptr;
32}
33
22void 34void
23deque_init(struct deque *d) 35deque_init(struct deque *d)
24{ 36{
37 assert(d != NULL);
38
25 d->map_begin = 0; 39 d->map_begin = 0;
26 d->map_end = 0; 40 d->map_end = 0;
27 d->offset = 0; 41 d->offset = 0;
28 d->size = 0; 42 d->size = 0;
29 43
30 // TODO: Error handling 44 // TODO: Error handling
31 d->map = calloc(START_MAP_CAPACITY, sizeof *d->map); 45 d->map = allocate(START_MAP_CAPACITY, sizeof *d->map);
32 if ( d->map != NULL ) { 46 if ( d->map != NULL ) {
33 d->map_capacity = START_MAP_CAPACITY; 47 d->map_capacity = START_MAP_CAPACITY;
34 48
@@ -41,6 +55,8 @@ deque_init(struct deque *d)
41void 55void
42deque_free(struct deque *d) 56deque_free(struct deque *d)
43{ 57{
58 assert(d != NULL);
59
44 // free all chunks 60 // free all chunks
45 for ( size_t i = 0; i != d->map_capacity; ++i ) { 61 for ( size_t i = 0; i != d->map_capacity; ++i ) {
46 free(d->map[i]); 62 free(d->map[i]);
@@ -54,20 +70,26 @@ deque_free(struct deque *d)
54size_t 70size_t
55deque_size(struct deque *d) 71deque_size(struct deque *d)
56{ 72{
73 assert(d != NULL);
74
57 return d->size; 75 return d->size;
58} 76}
59 77
60bool 78bool
61deque_is_empty(struct deque *d) 79deque_is_empty(struct deque *d)
62{ 80{
81 assert(d != NULL);
82
63 return d->map_begin == d->map_end; 83 return d->map_begin == d->map_end;
64} 84}
65 85
66static void 86static void
67grow_map(struct deque *d) 87grow_map(struct deque *d)
68{ 88{
89 assert(d != NULL);
90
69 const size_t capacity = d->map_capacity + d->map_capacity / 2; 91 const size_t capacity = d->map_capacity + d->map_capacity / 2;
70 T ** map = calloc(capacity, sizeof *map); 92 T ** map = allocate(capacity, sizeof *map);
71 93
72 // copy elements 94 // copy elements
73 size_t i, j; 95 size_t i, j;
@@ -98,6 +120,8 @@ grow_map(struct deque *d)
98static void 120static void
99map_append_chunk(struct deque *d) 121map_append_chunk(struct deque *d)
100{ 122{
123 assert(d != NULL);
124
101 size_t next = (d->map_end + 1) % d->map_capacity; 125 size_t next = (d->map_end + 1) % d->map_capacity;
102 126
103 if ( next == d->map_begin ) { // Resize the map 127 if ( next == d->map_begin ) { // Resize the map
@@ -106,13 +130,15 @@ map_append_chunk(struct deque *d)
106 next = d->map_end + 1; 130 next = d->map_end + 1;
107 } 131 }
108 132
109 d->map[d->map_end] = calloc(CHUNK_CAPACITY, sizeof **d->map); 133 d->map[d->map_end] = allocate(CHUNK_CAPACITY, sizeof **d->map);
110 d->map_end = next; 134 d->map_end = next;
111} 135}
112 136
113static void 137static void
114map_prepend_chunk(struct deque *d) 138map_prepend_chunk(struct deque *d)
115{ 139{
140 assert(d != NULL);
141
116 size_t prev = (d->map_begin + d->map_capacity - 1) % d->map_capacity; 142 size_t prev = (d->map_begin + d->map_capacity - 1) % d->map_capacity;
117 143
118 if ( prev == d->map_end ) { 144 if ( prev == d->map_end ) {
@@ -121,13 +147,15 @@ map_prepend_chunk(struct deque *d)
121 prev = d->map_capacity - 1; 147 prev = d->map_capacity - 1;
122 } 148 }
123 149
124 d->map[prev] = calloc(CHUNK_CAPACITY, sizeof **d->map); 150 d->map[prev] = allocate(CHUNK_CAPACITY, sizeof **d->map);
125 d->map_begin = prev; 151 d->map_begin = prev;
126} 152}
127 153
128static void 154static void
129map_remove_front_chunk(struct deque *d) 155map_remove_front_chunk(struct deque *d)
130{ 156{
157 assert(d != NULL);
158
131 if ( d->map_begin == d->map_end ) { 159 if ( d->map_begin == d->map_end ) {
132 return; 160 return;
133 } 161 }
@@ -143,6 +171,8 @@ map_remove_front_chunk(struct deque *d)
143static void 171static void
144map_remove_tail_chunk(struct deque *d) 172map_remove_tail_chunk(struct deque *d)
145{ 173{
174 assert(d != NULL);
175
146 if ( d->map_begin == d->map_end ) { 176 if ( d->map_begin == d->map_end ) {
147 return; 177 return;
148 } 178 }
@@ -158,6 +188,10 @@ map_remove_tail_chunk(struct deque *d)
158bool 188bool
159deque_get_at(struct deque *d, size_t idx, T *data) 189deque_get_at(struct deque *d, size_t idx, T *data)
160{ 190{
191 assert(d != NULL);
192 assert(idx < d->size);
193 assert(data != NULL);
194
161 if ( idx >= d->size ) { 195 if ( idx >= d->size ) {
162 return false; 196 return false;
163 } 197 }
@@ -174,6 +208,9 @@ deque_get_at(struct deque *d, size_t idx, T *data)
174bool 208bool
175deque_set_at(struct deque *d, size_t idx, T data) 209deque_set_at(struct deque *d, size_t idx, T data)
176{ 210{
211 assert(d != NULL);
212 assert(idx < d->size);
213
177 if ( idx >= d->size ) { 214 if ( idx >= d->size ) {
178 return false; 215 return false;
179 } 216 }
@@ -190,6 +227,8 @@ deque_set_at(struct deque *d, size_t idx, T data)
190void 227void
191deque_push_back(struct deque *d, T data) 228deque_push_back(struct deque *d, T data)
192{ 229{
230 assert(d != NULL);
231
193 const size_t pos = d->offset + d->size; 232 const size_t pos = d->offset + d->size;
194 const size_t chunk_off = pos % CHUNK_CAPACITY; 233 const size_t chunk_off = pos % CHUNK_CAPACITY;
195 size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity; 234 size_t chunk_num = (pos / CHUNK_CAPACITY + d->map_begin) % d->map_capacity;
@@ -206,6 +245,8 @@ deque_push_back(struct deque *d, T data)
206void 245void
207deque_push_front(struct deque *d, T data) 246deque_push_front(struct deque *d, T data)
208{ 247{
248 assert(d != NULL);
249
209 if ( d->offset == 0 ) { // Im ersten Element ist kein Platz mehr frei! 250 if ( d->offset == 0 ) { // Im ersten Element ist kein Platz mehr frei!
210 map_prepend_chunk(d); 251 map_prepend_chunk(d);
211 d->offset = CHUNK_CAPACITY; 252 d->offset = CHUNK_CAPACITY;
@@ -222,6 +263,9 @@ deque_push_front(struct deque *d, T data)
222bool 263bool
223deque_pop_back(struct deque *d, T *data) 264deque_pop_back(struct deque *d, T *data)
224{ 265{
266 assert(d != NULL);
267 assert(data != NULL);
268
225 if ( d->size == 0 ) { 269 if ( d->size == 0 ) {
226 return false; 270 return false;
227 } 271 }
@@ -244,6 +288,9 @@ deque_pop_back(struct deque *d, T *data)
244bool 288bool
245deque_pop_front(struct deque *d, T *data) 289deque_pop_front(struct deque *d, T *data)
246{ 290{
291 assert(d != NULL);
292 assert(data != NULL);
293
247 if ( d->size == 0 ) { 294 if ( d->size == 0 ) {
248 return false; 295 return false;
249 } 296 }
@@ -267,6 +314,8 @@ deque_pop_front(struct deque *d, T *data)
267static void 314static void
268deque_show(struct deque *d) 315deque_show(struct deque *d)
269{ 316{
317 assert(d != NULL);
318
270 printf("first: %zu -- last: %zu -- size: %zu -- map_capacity: %zu -- offset: %zu\n", 319 printf("first: %zu -- last: %zu -- size: %zu -- map_capacity: %zu -- offset: %zu\n",
271 d->map_begin, d->map_end, d->size, d->map_capacity, d->offset); 320 d->map_begin, d->map_end, d->size, d->map_capacity, d->offset);
272 for ( size_t i = 0; i != d->map_capacity; ++i ) { 321 for ( size_t i = 0; i != d->map_capacity; ++i ) {
@@ -374,6 +423,8 @@ test_deque(void)
374 assert(deque_size(d) == 0); 423 assert(deque_size(d) == 0);
375 424
376 deque_free(d); 425 deque_free(d);
426
427 puts("all tests passed.");
377} 428}
378 429
379int 430int