1 /*
2 The MIT License(MIT)
3 Copyright(c) 2016 Peter Goldsborough
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions :
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #define __STDC_WANT_LIB_EXT1__ 1
24
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "third_party/vector/vector.h"
30
31 /***** PRIVATE *****/
32 #define MAX(a, b) ((a) > (b) ? (a) : (b))
33
_vector_should_grow(Vector * vector)34 static bool _vector_should_grow(Vector *vector) {
35 assert(vector->size <= vector->capacity);
36 return vector->size == vector->capacity;
37 }
38
_vector_should_shrink(Vector * vector)39 static bool _vector_should_shrink(Vector *vector) {
40 assert(vector->size <= vector->capacity);
41 return vector->size == vector->capacity * VECTOR_SHRINK_THRESHOLD;
42 }
43
_vector_offset(Vector * vector,size_t index)44 static void *_vector_offset(Vector *vector, size_t index) {
45 // return vector->data + (index * vector->element_size);
46 return (unsigned char *)vector->data + (index * vector->element_size);
47 }
48
_vector_const_offset(const Vector * vector,size_t index)49 static const void *_vector_const_offset(const Vector *vector, size_t index) {
50 // return vector->data + (index * vector->element_size);
51 return (unsigned char *)vector->data + (index * vector->element_size);
52 }
53
_vector_assign(Vector * vector,size_t index,void * element)54 static void _vector_assign(Vector *vector, size_t index, void *element) {
55 /* Insert the element */
56 void *offset = _vector_offset(vector, index);
57 memcpy(offset, element, vector->element_size);
58 }
59
_vector_move_right(Vector * vector,size_t index)60 static int _vector_move_right(Vector *vector, size_t index) {
61 assert(vector->size < vector->capacity);
62
63 /* The location where to start to move from. */
64 void *offset = _vector_offset(vector, index);
65
66 /* How many to move to the right. */
67 size_t elements_in_bytes = (vector->size - index) * vector->element_size;
68
69 #ifdef __STDC_LIB_EXT1__
70 size_t right_capacity_in_bytes =
71 (vector->capacity - (index + 1)) * vector->element_size;
72
73 /* clang-format off */
74 int return_code = memmove_s(
75 offset + vector->element_size,
76 right_capacity_in_bytes,
77 offset,
78 elements_in_bytes);
79
80 /* clang-format on */
81
82 return return_code == 0 ? VECTOR_SUCCESS : VECTOR_ERROR;
83
84 #else
85 // memmove(offset + vector->element_size, offset, elements_in_bytes);
86 memmove((unsigned char *)offset + vector->element_size, offset,
87 elements_in_bytes);
88 return VECTOR_SUCCESS;
89 #endif
90 }
91
_vector_move_left(Vector * vector,size_t index)92 static void _vector_move_left(Vector *vector, size_t index) {
93 size_t right_elements_in_bytes;
94 void *offset;
95
96 /* The offset into the memory */
97 offset = _vector_offset(vector, index);
98
99 /* How many to move to the left */
100 right_elements_in_bytes = (vector->size - index - 1) * vector->element_size;
101
102 // memmove(offset, offset + vector->element_size, right_elements_in_bytes);
103 memmove(offset, (unsigned char *)offset + vector->element_size,
104 right_elements_in_bytes);
105 }
106
_vector_reallocate(Vector * vector,size_t new_capacity)107 static int _vector_reallocate(Vector *vector, size_t new_capacity) {
108 size_t new_capacity_in_bytes;
109 void *old;
110 assert(vector != NULL);
111
112 if (new_capacity < VECTOR_MINIMUM_CAPACITY) {
113 if (vector->capacity > VECTOR_MINIMUM_CAPACITY) {
114 new_capacity = VECTOR_MINIMUM_CAPACITY;
115 } else {
116 /* NO-OP */
117 return VECTOR_SUCCESS;
118 }
119 }
120
121 new_capacity_in_bytes = new_capacity * vector->element_size;
122 old = vector->data;
123
124 if ((vector->data = malloc(new_capacity_in_bytes)) == NULL) {
125 return VECTOR_ERROR;
126 }
127
128 #ifdef __STDC_LIB_EXT1__
129 /* clang-format off */
130 if (memcpy_s(vector->data,
131 new_capacity_in_bytes,
132 old,
133 aom_vector_byte_size(vector)) != 0) {
134 return VECTOR_ERROR;
135 }
136 /* clang-format on */
137 #else
138 memcpy(vector->data, old, aom_vector_byte_size(vector));
139 #endif
140
141 vector->capacity = new_capacity;
142
143 free(old);
144
145 return VECTOR_SUCCESS;
146 }
147
_vector_adjust_capacity(Vector * vector)148 static int _vector_adjust_capacity(Vector *vector) {
149 return _vector_reallocate(vector,
150 MAX(1, vector->size * VECTOR_GROWTH_FACTOR));
151 }
152
_vector_swap(size_t * first,size_t * second)153 static void _vector_swap(size_t *first, size_t *second) {
154 size_t temp = *first;
155 *first = *second;
156 *second = temp;
157 }
158
aom_vector_setup(Vector * vector,size_t capacity,size_t element_size)159 int aom_vector_setup(Vector *vector, size_t capacity, size_t element_size) {
160 assert(vector != NULL);
161
162 if (vector == NULL) return VECTOR_ERROR;
163
164 vector->size = 0;
165 vector->capacity = MAX(VECTOR_MINIMUM_CAPACITY, capacity);
166 vector->element_size = element_size;
167 vector->data = malloc(vector->capacity * element_size);
168
169 return vector->data == NULL ? VECTOR_ERROR : VECTOR_SUCCESS;
170 }
171
aom_vector_copy(Vector * destination,Vector * source)172 int aom_vector_copy(Vector *destination, Vector *source) {
173 assert(destination != NULL);
174 assert(source != NULL);
175 assert(aom_vector_is_initialized(source));
176 assert(!aom_vector_is_initialized(destination));
177
178 if (destination == NULL) return VECTOR_ERROR;
179 if (source == NULL) return VECTOR_ERROR;
180 if (aom_vector_is_initialized(destination)) return VECTOR_ERROR;
181 if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
182
183 /* Copy ALL the data */
184 destination->size = source->size;
185 destination->capacity = source->size * 2;
186 destination->element_size = source->element_size;
187
188 /* Note that we are not necessarily allocating the same capacity */
189 destination->data = malloc(destination->capacity * source->element_size);
190 if (destination->data == NULL) return VECTOR_ERROR;
191
192 memcpy(destination->data, source->data, aom_vector_byte_size(source));
193
194 return VECTOR_SUCCESS;
195 }
196
aom_vector_copy_assign(Vector * destination,Vector * source)197 int aom_vector_copy_assign(Vector *destination, Vector *source) {
198 assert(destination != NULL);
199 assert(source != NULL);
200 assert(aom_vector_is_initialized(source));
201 assert(aom_vector_is_initialized(destination));
202
203 if (destination == NULL) return VECTOR_ERROR;
204 if (source == NULL) return VECTOR_ERROR;
205 if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR;
206 if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
207
208 aom_vector_destroy(destination);
209
210 return aom_vector_copy(destination, source);
211 }
212
aom_vector_move(Vector * destination,Vector * source)213 int aom_vector_move(Vector *destination, Vector *source) {
214 assert(destination != NULL);
215 assert(source != NULL);
216
217 if (destination == NULL) return VECTOR_ERROR;
218 if (source == NULL) return VECTOR_ERROR;
219
220 *destination = *source;
221 source->data = NULL;
222
223 return VECTOR_SUCCESS;
224 }
225
aom_vector_move_assign(Vector * destination,Vector * source)226 int aom_vector_move_assign(Vector *destination, Vector *source) {
227 aom_vector_swap(destination, source);
228 return aom_vector_destroy(source);
229 }
230
aom_vector_swap(Vector * destination,Vector * source)231 int aom_vector_swap(Vector *destination, Vector *source) {
232 void *temp;
233
234 assert(destination != NULL);
235 assert(source != NULL);
236 assert(aom_vector_is_initialized(source));
237 assert(aom_vector_is_initialized(destination));
238
239 if (destination == NULL) return VECTOR_ERROR;
240 if (source == NULL) return VECTOR_ERROR;
241 if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR;
242 if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
243
244 _vector_swap(&destination->size, &source->size);
245 _vector_swap(&destination->capacity, &source->capacity);
246 _vector_swap(&destination->element_size, &source->element_size);
247
248 temp = destination->data;
249 destination->data = source->data;
250 source->data = temp;
251
252 return VECTOR_SUCCESS;
253 }
254
aom_vector_destroy(Vector * vector)255 int aom_vector_destroy(Vector *vector) {
256 assert(vector != NULL);
257
258 if (vector == NULL) return VECTOR_ERROR;
259
260 free(vector->data);
261 vector->data = NULL;
262
263 return VECTOR_SUCCESS;
264 }
265
266 /* Insertion */
aom_vector_push_back(Vector * vector,void * element)267 int aom_vector_push_back(Vector *vector, void *element) {
268 assert(vector != NULL);
269 assert(element != NULL);
270
271 if (_vector_should_grow(vector)) {
272 if (_vector_adjust_capacity(vector) == VECTOR_ERROR) {
273 return VECTOR_ERROR;
274 }
275 }
276
277 _vector_assign(vector, vector->size, element);
278
279 ++vector->size;
280
281 return VECTOR_SUCCESS;
282 }
283
aom_vector_push_front(Vector * vector,void * element)284 int aom_vector_push_front(Vector *vector, void *element) {
285 return aom_vector_insert(vector, 0, element);
286 }
287
aom_vector_insert(Vector * vector,size_t index,void * element)288 int aom_vector_insert(Vector *vector, size_t index, void *element) {
289 void *offset;
290
291 assert(vector != NULL);
292 assert(element != NULL);
293 assert(index <= vector->size);
294
295 if (vector == NULL) return VECTOR_ERROR;
296 if (element == NULL) return VECTOR_ERROR;
297 if (vector->element_size == 0) return VECTOR_ERROR;
298 if (index > vector->size) return VECTOR_ERROR;
299
300 if (_vector_should_grow(vector)) {
301 if (_vector_adjust_capacity(vector) == VECTOR_ERROR) {
302 return VECTOR_ERROR;
303 }
304 }
305
306 /* Move other elements to the right */
307 if (_vector_move_right(vector, index) == VECTOR_ERROR) {
308 return VECTOR_ERROR;
309 }
310
311 /* Insert the element */
312 offset = _vector_offset(vector, index);
313 memcpy(offset, element, vector->element_size);
314 ++vector->size;
315
316 return VECTOR_SUCCESS;
317 }
318
aom_vector_assign(Vector * vector,size_t index,void * element)319 int aom_vector_assign(Vector *vector, size_t index, void *element) {
320 assert(vector != NULL);
321 assert(element != NULL);
322 assert(index < vector->size);
323
324 if (vector == NULL) return VECTOR_ERROR;
325 if (element == NULL) return VECTOR_ERROR;
326 if (vector->element_size == 0) return VECTOR_ERROR;
327 if (index >= vector->size) return VECTOR_ERROR;
328
329 _vector_assign(vector, index, element);
330
331 return VECTOR_SUCCESS;
332 }
333
334 /* Deletion */
aom_vector_pop_back(Vector * vector)335 int aom_vector_pop_back(Vector *vector) {
336 assert(vector != NULL);
337 assert(vector->size > 0);
338
339 if (vector == NULL) return VECTOR_ERROR;
340 if (vector->element_size == 0) return VECTOR_ERROR;
341
342 --vector->size;
343
344 #ifndef VECTOR_NO_SHRINK
345 if (_vector_should_shrink(vector)) {
346 _vector_adjust_capacity(vector);
347 }
348 #endif
349
350 return VECTOR_SUCCESS;
351 }
352
aom_vector_pop_front(Vector * vector)353 int aom_vector_pop_front(Vector *vector) { return aom_vector_erase(vector, 0); }
354
aom_vector_erase(Vector * vector,size_t index)355 int aom_vector_erase(Vector *vector, size_t index) {
356 assert(vector != NULL);
357 assert(index < vector->size);
358
359 if (vector == NULL) return VECTOR_ERROR;
360 if (vector->element_size == 0) return VECTOR_ERROR;
361 if (index >= vector->size) return VECTOR_ERROR;
362
363 /* Just overwrite */
364 _vector_move_left(vector, index);
365
366 #ifndef VECTOR_NO_SHRINK
367 if (--vector->size == vector->capacity / 4) {
368 _vector_adjust_capacity(vector);
369 }
370 #endif
371
372 return VECTOR_SUCCESS;
373 }
374
aom_vector_clear(Vector * vector)375 int aom_vector_clear(Vector *vector) { return aom_vector_resize(vector, 0); }
376
377 /* Lookup */
aom_vector_get(Vector * vector,size_t index)378 void *aom_vector_get(Vector *vector, size_t index) {
379 assert(vector != NULL);
380 assert(index < vector->size);
381
382 if (vector == NULL) return NULL;
383 if (vector->element_size == 0) return NULL;
384 if (index >= vector->size) return NULL;
385
386 return _vector_offset(vector, index);
387 }
388
aom_vector_const_get(const Vector * vector,size_t index)389 const void *aom_vector_const_get(const Vector *vector, size_t index) {
390 assert(vector != NULL);
391 assert(index < vector->size);
392
393 if (vector == NULL) return NULL;
394 if (vector->element_size == 0) return NULL;
395 if (index >= vector->size) return NULL;
396
397 return _vector_const_offset(vector, index);
398 }
399
aom_vector_front(Vector * vector)400 void *aom_vector_front(Vector *vector) { return aom_vector_get(vector, 0); }
401
aom_vector_back(Vector * vector)402 void *aom_vector_back(Vector *vector) {
403 return aom_vector_get(vector, vector->size - 1);
404 }
405
406 /* Information */
407
aom_vector_is_initialized(const Vector * vector)408 bool aom_vector_is_initialized(const Vector *vector) {
409 return vector->data != NULL;
410 }
411
aom_vector_byte_size(const Vector * vector)412 size_t aom_vector_byte_size(const Vector *vector) {
413 return vector->size * vector->element_size;
414 }
415
aom_vector_free_space(const Vector * vector)416 size_t aom_vector_free_space(const Vector *vector) {
417 return vector->capacity - vector->size;
418 }
419
aom_vector_is_empty(const Vector * vector)420 bool aom_vector_is_empty(const Vector *vector) { return vector->size == 0; }
421
422 /* Memory management */
aom_vector_resize(Vector * vector,size_t new_size)423 int aom_vector_resize(Vector *vector, size_t new_size) {
424 if (new_size <= vector->capacity * VECTOR_SHRINK_THRESHOLD) {
425 vector->size = new_size;
426 if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) {
427 return VECTOR_ERROR;
428 }
429 } else if (new_size > vector->capacity) {
430 if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) {
431 return VECTOR_ERROR;
432 }
433 }
434
435 vector->size = new_size;
436
437 return VECTOR_SUCCESS;
438 }
439
aom_vector_reserve(Vector * vector,size_t minimum_capacity)440 int aom_vector_reserve(Vector *vector, size_t minimum_capacity) {
441 if (minimum_capacity > vector->capacity) {
442 if (_vector_reallocate(vector, minimum_capacity) == VECTOR_ERROR) {
443 return VECTOR_ERROR;
444 }
445 }
446
447 return VECTOR_SUCCESS;
448 }
449
aom_vector_shrink_to_fit(Vector * vector)450 int aom_vector_shrink_to_fit(Vector *vector) {
451 return _vector_reallocate(vector, vector->size);
452 }
453
454 /* Iterators */
aom_vector_begin(Vector * vector)455 Iterator aom_vector_begin(Vector *vector) { return aom_vector_iterator(vector, 0); }
456
aom_vector_end(Vector * vector)457 Iterator aom_vector_end(Vector *vector) {
458 return aom_vector_iterator(vector, vector->size);
459 }
460
aom_vector_iterator(Vector * vector,size_t index)461 Iterator aom_vector_iterator(Vector *vector, size_t index) {
462 Iterator iterator = { NULL, 0 };
463
464 assert(vector != NULL);
465 assert(index <= vector->size);
466
467 if (vector == NULL) return iterator;
468 if (index > vector->size) return iterator;
469 if (vector->element_size == 0) return iterator;
470
471 iterator.pointer = _vector_offset(vector, index);
472 iterator.element_size = vector->element_size;
473
474 return iterator;
475 }
476
aom_iterator_get(Iterator * iterator)477 void *aom_iterator_get(Iterator *iterator) { return iterator->pointer; }
478
aom_iterator_erase(Vector * vector,Iterator * iterator)479 int aom_iterator_erase(Vector *vector, Iterator *iterator) {
480 size_t index = aom_iterator_index(vector, iterator);
481
482 if (aom_vector_erase(vector, index) == VECTOR_ERROR) {
483 return VECTOR_ERROR;
484 }
485
486 *iterator = aom_vector_iterator(vector, index);
487
488 return VECTOR_SUCCESS;
489 }
490
aom_iterator_increment(Iterator * iterator)491 void aom_iterator_increment(Iterator *iterator) {
492 assert(iterator != NULL);
493 // iterator->pointer += iterator->element_size;
494 iterator->pointer =
495 (unsigned char *)iterator->pointer + iterator->element_size;
496 }
497
aom_iterator_decrement(Iterator * iterator)498 void aom_iterator_decrement(Iterator *iterator) {
499 assert(iterator != NULL);
500 // iterator->pointer -= iterator->element_size;
501 iterator->pointer =
502 (unsigned char *)iterator->pointer - iterator->element_size;
503 }
504
aom_iterator_next(Iterator * iterator)505 void *aom_iterator_next(Iterator *iterator) {
506 void *current = iterator->pointer;
507 aom_iterator_increment(iterator);
508
509 return current;
510 }
511
aom_iterator_previous(Iterator * iterator)512 void *aom_iterator_previous(Iterator *iterator) {
513 void *current = iterator->pointer;
514 aom_iterator_decrement(iterator);
515
516 return current;
517 }
518
aom_iterator_equals(Iterator * first,Iterator * second)519 bool aom_iterator_equals(Iterator *first, Iterator *second) {
520 assert(first->element_size == second->element_size);
521 return first->pointer == second->pointer;
522 }
523
aom_iterator_is_before(Iterator * first,Iterator * second)524 bool aom_iterator_is_before(Iterator *first, Iterator *second) {
525 assert(first->element_size == second->element_size);
526 return first->pointer < second->pointer;
527 }
528
aom_iterator_is_after(Iterator * first,Iterator * second)529 bool aom_iterator_is_after(Iterator *first, Iterator *second) {
530 assert(first->element_size == second->element_size);
531 return first->pointer > second->pointer;
532 }
533
aom_iterator_index(Vector * vector,Iterator * iterator)534 size_t aom_iterator_index(Vector *vector, Iterator *iterator) {
535 assert(vector != NULL);
536 assert(iterator != NULL);
537 // return (iterator->pointer - vector->data) / vector->element_size;
538 return ((unsigned char *)iterator->pointer - (unsigned char *)vector->data) /
539 vector->element_size;
540 }
541