aboutsummaryrefslogtreecommitdiff
path: root/deque.c
diff options
context:
space:
mode:
Diffstat (limited to 'deque.c')
-rw-r--r--deque.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/deque.c b/deque.c
index 168669e..c4b1795 100644
--- a/deque.c
+++ b/deque.c
@@ -3,7 +3,7 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5 5
6#define NELEM(x) (sizeof(x) / sizeof(x[0])) 6#include "util.h"
7 7
8typedef int T; 8typedef int T;
9 9
@@ -21,16 +21,28 @@ struct deque {
21 size_t size; 21 size_t size;
22}; 22};
23 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
24void 34void
25deque_init(struct deque *d) 35deque_init(struct deque *d)
26{ 36{
37 assert(d != NULL);
38
27 d->map_begin = 0; 39 d->map_begin = 0;
28 d->map_end = 0; 40 d->map_end = 0;
29 d->offset = 0; 41 d->offset = 0;
30 d->size = 0; 42 d->size = 0;
31 43
32 // TODO: Error handling 44 // TODO: Error handling
33 d->map = calloc(START_MAP_CAPACITY, sizeof *d->map); 45 d->map = allocate(START_MAP_CAPACITY, sizeof *d->map);
34 if ( d->map != NULL ) { 46 if ( d->map != NULL ) {
35 d->map_capacity = START_MAP_CAPACITY; 47 d->map_capacity = START_MAP_CAPACITY;
36 48
@@ -43,6 +55,8 @@ deque_init(struct deque *d)
43void 55void
44deque_free(struct deque *d) 56deque_free(struct deque *d)
45{ 57{
58 assert(d != NULL);
59
46 // free all chunks 60 // free all chunks
47 for ( size_t i = 0; i != d->map_capacity; ++i ) { 61 for ( size_t i = 0; i != d->map_capacity; ++i ) {
48 free(d->map[i]); 62 free(d->map[i]);
@@ -56,20 +70,26 @@ deque_free(struct deque *d)
56size_t 70size_t
57deque_size(struct deque *d) 71deque_size(struct deque *d)
58{ 72{
73 assert(d != NULL);
74
59 return d->size; 75 return d->size;
60} 76}
61 77
62bool 78bool
63deque_is_empty(struct deque *d) 79deque_is_empty(struct deque *d)
64{ 80{
81 assert(d != NULL);
82
65 return d->map_begin == d->map_end; 83 return d->map_begin == d->map_end;
66} 84}
67 85
68static void 86static void
69grow_map(struct deque *d) 87grow_map(struct deque *d)
70{ 88{
89 assert(d != NULL);
90
71 const size_t capacity = d->map_capacity + d->map_capacity / 2; 91 const size_t capacity = d->map_capacity + d->map_capacity / 2;
72 T ** map = calloc(capacity, sizeof *map); 92 T ** map = allocate(capacity, sizeof *map);
73 93
74 // copy elements 94 // copy elements
75 size_t i, j; 95 size_t i, j;
@@ -100,6 +120,8 @@ grow_map(struct deque *d)
100static void 120static void
101map_append_chunk(struct deque *d) 121map_append_chunk(struct deque *d)
102{ 122{
123 assert(d != NULL);
124
103 size_t next = (d->map_end + 1) % d->map_capacity; 125 size_t next = (d->map_end + 1) % d->map_capacity;
104 126
105 if ( next == d->map_begin ) { // Resize the map 127 if ( next == d->map_begin ) { // Resize the map
@@ -108,13 +130,15 @@ map_append_chunk(struct deque *d)
108 next = d->map_end + 1; 130 next = d->map_end + 1;
109 } 131 }
110 132
111 d->map[d->map_end] = calloc(CHUNK_CAPACITY, sizeof **d->map); 133 d->map[d->map_end] = allocate(CHUNK_CAPACITY, sizeof **d->map);
112 d->map_end = next; 134 d->map_end = next;
113} 135}
114 136
115static void 137static void
116map_prepend_chunk(struct deque *d) 138map_prepend_chunk(struct deque *d)
117{ 139{
140 assert(d != NULL);
141
118 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;
119 143
120 if ( prev == d->map_end ) { 144 if ( prev == d->map_end ) {
@@ -123,13 +147,15 @@ map_prepend_chunk(struct deque *d)
123 prev = d->map_capacity - 1; 147 prev = d->map_capacity - 1;
124 } 148 }
125 149
126 d->map[prev] = calloc(CHUNK_CAPACITY, sizeof **d->map); 150 d->map[prev] = allocate(CHUNK_CAPACITY, sizeof **d->map);
127 d->map_begin = prev; 151 d->map_begin = prev;
128} 152}
129 153
130static void 154static void
131map_remove_front_chunk(struct deque *d) 155map_remove_front_chunk(struct deque *d)
132{ 156{
157 assert(d != NULL);
158
133 if ( d->map_begin == d->map_end ) { 159 if ( d->map_begin == d->map_end ) {
134 return; 160 return;
135 } 161 }
@@ -145,6 +171,8 @@ map_remove_front_chunk(struct deque *d)
145static void 171static void
146map_remove_tail_chunk(struct deque *d) 172map_remove_tail_chunk(struct deque *d)
147{ 173{
174 assert(d != NULL);
175
148 if ( d->map_begin == d->map_end ) { 176 if ( d->map_begin == d->map_end ) {
149 return; 177 return;
150 } 178 }
@@ -160,6 +188,10 @@ map_remove_tail_chunk(struct deque *d)
160bool 188bool
161deque_get_at(struct deque *d, size_t idx, T *data) 189deque_get_at(struct deque *d, size_t idx, T *data)
162{ 190{
191 assert(d != NULL);
192 assert(idx < d->size);
193 assert(data != NULL);
194
163 if ( idx >= d->size ) { 195 if ( idx >= d->size ) {
164 return false; 196 return false;
165 } 197 }
@@ -176,6 +208,9 @@ deque_get_at(struct deque *d, size_t idx, T *data)
176bool 208bool
177deque_set_at(struct deque *d, size_t idx, T data) 209deque_set_at(struct deque *d, size_t idx, T data)
178{ 210{
211 assert(d != NULL);
212 assert(idx < d->size);
213
179 if ( idx >= d->size ) { 214 if ( idx >= d->size ) {
180 return false; 215 return false;
181 } 216 }
@@ -192,6 +227,8 @@ deque_set_at(struct deque *d, size_t idx, T data)
192void 227void
193deque_push_back(struct deque *d, T data) 228deque_push_back(struct deque *d, T data)
194{ 229{
230 assert(d != NULL);
231
195 const size_t pos = d->offset + d->size; 232 const size_t pos = d->offset + d->size;
196 const size_t chunk_off = pos % CHUNK_CAPACITY; 233 const size_t chunk_off = pos % CHUNK_CAPACITY;
197 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;
@@ -208,6 +245,8 @@ deque_push_back(struct deque *d, T data)
208void 245void
209deque_push_front(struct deque *d, T data) 246deque_push_front(struct deque *d, T data)
210{ 247{
248 assert(d != NULL);
249
211 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!
212 map_prepend_chunk(d); 251 map_prepend_chunk(d);
213 d->offset = CHUNK_CAPACITY; 252 d->offset = CHUNK_CAPACITY;
@@ -224,6 +263,9 @@ deque_push_front(struct deque *d, T data)
224bool 263bool
225deque_pop_back(struct deque *d, T *data) 264deque_pop_back(struct deque *d, T *data)
226{ 265{
266 assert(d != NULL);
267 assert(data != NULL);
268
227 if ( d->size == 0 ) { 269 if ( d->size == 0 ) {
228 return false; 270 return false;
229 } 271 }
@@ -246,6 +288,9 @@ deque_pop_back(struct deque *d, T *data)
246bool 288bool
247deque_pop_front(struct deque *d, T *data) 289deque_pop_front(struct deque *d, T *data)
248{ 290{
291 assert(d != NULL);
292 assert(data != NULL);
293
249 if ( d->size == 0 ) { 294 if ( d->size == 0 ) {
250 return false; 295 return false;
251 } 296 }
@@ -269,6 +314,8 @@ deque_pop_front(struct deque *d, T *data)
269static void 314static void
270deque_show(struct deque *d) 315deque_show(struct deque *d)
271{ 316{
317 assert(d != NULL);
318
272 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",
273 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);
274 for ( size_t i = 0; i != d->map_capacity; ++i ) { 321 for ( size_t i = 0; i != d->map_capacity; ++i ) {
@@ -284,7 +331,7 @@ test_deque(void)
284 331
285 deque_init(d); 332 deque_init(d);
286 333
287 const int N = 10000000; 334 const int N = 100000;
288 335
289 for ( int i = 0; i != N; ++i ) { 336 for ( int i = 0; i != N; ++i ) {
290 deque_push_front(d, i); 337 deque_push_front(d, i);
@@ -296,6 +343,7 @@ test_deque(void)
296 assert(data == i); 343 assert(data == i);
297 } 344 }
298 assert(deque_is_empty(d) == true); 345 assert(deque_is_empty(d) == true);
346 assert(deque_size(d) == 0);
299 347
300 deque_free(d); 348 deque_free(d);
301 349
@@ -311,6 +359,7 @@ test_deque(void)
311 assert(data == i); 359 assert(data == i);
312 } 360 }
313 assert(deque_is_empty(d) == true); 361 assert(deque_is_empty(d) == true);
362 assert(deque_size(d) == 0);
314 363
315 deque_free(d); 364 deque_free(d);
316 365
@@ -326,6 +375,7 @@ test_deque(void)
326 assert(data == i); 375 assert(data == i);
327 } 376 }
328 assert(deque_is_empty(d) == true); 377 assert(deque_is_empty(d) == true);
378 assert(deque_size(d) == 0);
329 379
330 deque_free(d); 380 deque_free(d);
331 381
@@ -354,6 +404,7 @@ test_deque(void)
354 assert(data == i); 404 assert(data == i);
355 } 405 }
356 assert(deque_is_empty(d) == true); 406 assert(deque_is_empty(d) == true);
407 assert(deque_size(d) == 0);
357 408
358 deque_free(d); 409 deque_free(d);
359 410
@@ -369,8 +420,11 @@ test_deque(void)
369 assert(data == i); 420 assert(data == i);
370 } 421 }
371 assert(deque_is_empty(d) == true); 422 assert(deque_is_empty(d) == true);
423 assert(deque_size(d) == 0);
372 424
373 deque_free(d); 425 deque_free(d);
426
427 puts("all tests passed.");
374} 428}
375 429
376int 430int