|  | /* | 
|  | The MIT License(MIT) | 
|  | Copyright(c) 2016 Peter Goldsborough | 
|  |  | 
|  | Permission is hereby granted, free of charge, to any person obtaining a copy of | 
|  | this software and associated documentation files(the "Software"), to deal in | 
|  | the Software without restriction, including without limitation the rights to | 
|  | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | 
|  | the Software, and to permit persons to whom the Software is furnished to do so, | 
|  | subject to the following conditions : | 
|  |  | 
|  | The above copyright notice and this permission notice shall be included in all | 
|  | copies or substantial portions of the Software. | 
|  |  | 
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | 
|  | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR | 
|  | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | 
|  | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
|  | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
|  | */ | 
|  |  | 
|  | #define __STDC_WANT_LIB_EXT1__ 1 | 
|  |  | 
|  | #include <assert.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "third_party/vector/vector.h" | 
|  |  | 
|  | int aom_vector_setup(Vector *vector, size_t capacity, size_t element_size) { | 
|  | assert(vector != NULL); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  |  | 
|  | vector->size = 0; | 
|  | vector->capacity = MAX(VECTOR_MINIMUM_CAPACITY, capacity); | 
|  | vector->element_size = element_size; | 
|  | vector->data = malloc(vector->capacity * element_size); | 
|  |  | 
|  | return vector->data == NULL ? VECTOR_ERROR : VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_copy(Vector *destination, Vector *source) { | 
|  | assert(destination != NULL); | 
|  | assert(source != NULL); | 
|  | assert(aom_vector_is_initialized(source)); | 
|  | assert(!aom_vector_is_initialized(destination)); | 
|  |  | 
|  | if (destination == NULL) return VECTOR_ERROR; | 
|  | if (source == NULL) return VECTOR_ERROR; | 
|  | if (aom_vector_is_initialized(destination)) return VECTOR_ERROR; | 
|  | if (!aom_vector_is_initialized(source)) return VECTOR_ERROR; | 
|  |  | 
|  | /* Copy ALL the data */ | 
|  | destination->size = source->size; | 
|  | destination->capacity = source->size * 2; | 
|  | destination->element_size = source->element_size; | 
|  |  | 
|  | /* Note that we are not necessarily allocating the same capacity */ | 
|  | destination->data = malloc(destination->capacity * source->element_size); | 
|  | if (destination->data == NULL) return VECTOR_ERROR; | 
|  |  | 
|  | memcpy(destination->data, source->data, aom_vector_byte_size(source)); | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_copy_assign(Vector *destination, Vector *source) { | 
|  | assert(destination != NULL); | 
|  | assert(source != NULL); | 
|  | assert(aom_vector_is_initialized(source)); | 
|  | assert(aom_vector_is_initialized(destination)); | 
|  |  | 
|  | if (destination == NULL) return VECTOR_ERROR; | 
|  | if (source == NULL) return VECTOR_ERROR; | 
|  | if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR; | 
|  | if (!aom_vector_is_initialized(source)) return VECTOR_ERROR; | 
|  |  | 
|  | aom_vector_destroy(destination); | 
|  |  | 
|  | return aom_vector_copy(destination, source); | 
|  | } | 
|  |  | 
|  | int aom_vector_move(Vector *destination, Vector *source) { | 
|  | assert(destination != NULL); | 
|  | assert(source != NULL); | 
|  |  | 
|  | if (destination == NULL) return VECTOR_ERROR; | 
|  | if (source == NULL) return VECTOR_ERROR; | 
|  |  | 
|  | *destination = *source; | 
|  | source->data = NULL; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_move_assign(Vector *destination, Vector *source) { | 
|  | aom_vector_swap(destination, source); | 
|  | return aom_vector_destroy(source); | 
|  | } | 
|  |  | 
|  | int aom_vector_swap(Vector *destination, Vector *source) { | 
|  | void *temp; | 
|  |  | 
|  | assert(destination != NULL); | 
|  | assert(source != NULL); | 
|  | assert(aom_vector_is_initialized(source)); | 
|  | assert(aom_vector_is_initialized(destination)); | 
|  |  | 
|  | if (destination == NULL) return VECTOR_ERROR; | 
|  | if (source == NULL) return VECTOR_ERROR; | 
|  | if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR; | 
|  | if (!aom_vector_is_initialized(source)) return VECTOR_ERROR; | 
|  |  | 
|  | _vector_swap(&destination->size, &source->size); | 
|  | _vector_swap(&destination->capacity, &source->capacity); | 
|  | _vector_swap(&destination->element_size, &source->element_size); | 
|  |  | 
|  | temp = destination->data; | 
|  | destination->data = source->data; | 
|  | source->data = temp; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_destroy(Vector *vector) { | 
|  | assert(vector != NULL); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  |  | 
|  | free(vector->data); | 
|  | vector->data = NULL; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | /* Insertion */ | 
|  | int aom_vector_push_back(Vector *vector, void *element) { | 
|  | assert(vector != NULL); | 
|  | assert(element != NULL); | 
|  |  | 
|  | if (_vector_should_grow(vector)) { | 
|  | if (_vector_adjust_capacity(vector) == VECTOR_ERROR) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | _vector_assign(vector, vector->size, element); | 
|  |  | 
|  | ++vector->size; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_push_front(Vector *vector, void *element) { | 
|  | return aom_vector_insert(vector, 0, element); | 
|  | } | 
|  |  | 
|  | int aom_vector_insert(Vector *vector, size_t index, void *element) { | 
|  | void *offset; | 
|  |  | 
|  | assert(vector != NULL); | 
|  | assert(element != NULL); | 
|  | assert(index <= vector->size); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  | if (element == NULL) return VECTOR_ERROR; | 
|  | if (vector->element_size == 0) return VECTOR_ERROR; | 
|  | if (index > vector->size) return VECTOR_ERROR; | 
|  |  | 
|  | if (_vector_should_grow(vector)) { | 
|  | if (_vector_adjust_capacity(vector) == VECTOR_ERROR) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Move other elements to the right */ | 
|  | if (_vector_move_right(vector, index) == VECTOR_ERROR) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  |  | 
|  | /* Insert the element */ | 
|  | offset = _vector_offset(vector, index); | 
|  | memcpy(offset, element, vector->element_size); | 
|  | ++vector->size; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_assign(Vector *vector, size_t index, void *element) { | 
|  | assert(vector != NULL); | 
|  | assert(element != NULL); | 
|  | assert(index < vector->size); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  | if (element == NULL) return VECTOR_ERROR; | 
|  | if (vector->element_size == 0) return VECTOR_ERROR; | 
|  | if (index >= vector->size) return VECTOR_ERROR; | 
|  |  | 
|  | _vector_assign(vector, index, element); | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | /* Deletion */ | 
|  | int aom_vector_pop_back(Vector *vector) { | 
|  | assert(vector != NULL); | 
|  | assert(vector->size > 0); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  | if (vector->element_size == 0) return VECTOR_ERROR; | 
|  |  | 
|  | --vector->size; | 
|  |  | 
|  | #ifndef VECTOR_NO_SHRINK | 
|  | if (_vector_should_shrink(vector)) { | 
|  | _vector_adjust_capacity(vector); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_pop_front(Vector *vector) { return aom_vector_erase(vector, 0); } | 
|  |  | 
|  | int aom_vector_erase(Vector *vector, size_t index) { | 
|  | assert(vector != NULL); | 
|  | assert(index < vector->size); | 
|  |  | 
|  | if (vector == NULL) return VECTOR_ERROR; | 
|  | if (vector->element_size == 0) return VECTOR_ERROR; | 
|  | if (index >= vector->size) return VECTOR_ERROR; | 
|  |  | 
|  | /* Just overwrite */ | 
|  | _vector_move_left(vector, index); | 
|  |  | 
|  | #ifndef VECTOR_NO_SHRINK | 
|  | if (--vector->size == vector->capacity / 4) { | 
|  | _vector_adjust_capacity(vector); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_clear(Vector *vector) { return aom_vector_resize(vector, 0); } | 
|  |  | 
|  | /* Lookup */ | 
|  | void *aom_vector_get(Vector *vector, size_t index) { | 
|  | assert(vector != NULL); | 
|  | assert(index < vector->size); | 
|  |  | 
|  | if (vector == NULL) return NULL; | 
|  | if (vector->element_size == 0) return NULL; | 
|  | if (index >= vector->size) return NULL; | 
|  |  | 
|  | return _vector_offset(vector, index); | 
|  | } | 
|  |  | 
|  | const void *aom_vector_const_get(const Vector *vector, size_t index) { | 
|  | assert(vector != NULL); | 
|  | assert(index < vector->size); | 
|  |  | 
|  | if (vector == NULL) return NULL; | 
|  | if (vector->element_size == 0) return NULL; | 
|  | if (index >= vector->size) return NULL; | 
|  |  | 
|  | return _vector_const_offset(vector, index); | 
|  | } | 
|  |  | 
|  | void *aom_vector_front(Vector *vector) { return aom_vector_get(vector, 0); } | 
|  |  | 
|  | void *aom_vector_back(Vector *vector) { | 
|  | return aom_vector_get(vector, vector->size - 1); | 
|  | } | 
|  |  | 
|  | /* Information */ | 
|  |  | 
|  | bool aom_vector_is_initialized(const Vector *vector) { | 
|  | return vector->data != NULL; | 
|  | } | 
|  |  | 
|  | size_t aom_vector_byte_size(const Vector *vector) { | 
|  | return vector->size * vector->element_size; | 
|  | } | 
|  |  | 
|  | size_t aom_vector_free_space(const Vector *vector) { | 
|  | return vector->capacity - vector->size; | 
|  | } | 
|  |  | 
|  | bool aom_vector_is_empty(const Vector *vector) { return vector->size == 0; } | 
|  |  | 
|  | /* Memory management */ | 
|  | int aom_vector_resize(Vector *vector, size_t new_size) { | 
|  | if (new_size <= vector->capacity * VECTOR_SHRINK_THRESHOLD) { | 
|  | vector->size = new_size; | 
|  | if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | } else if (new_size > vector->capacity) { | 
|  | if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | vector->size = new_size; | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_reserve(Vector *vector, size_t minimum_capacity) { | 
|  | if (minimum_capacity > vector->capacity) { | 
|  | if (_vector_reallocate(vector, minimum_capacity) == VECTOR_ERROR) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | } | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | int aom_vector_shrink_to_fit(Vector *vector) { | 
|  | return _vector_reallocate(vector, vector->size); | 
|  | } | 
|  |  | 
|  | /* Iterators */ | 
|  | Iterator aom_vector_begin(Vector *vector) { return aom_vector_iterator(vector, 0); } | 
|  |  | 
|  | Iterator aom_vector_end(Vector *vector) { | 
|  | return aom_vector_iterator(vector, vector->size); | 
|  | } | 
|  |  | 
|  | Iterator aom_vector_iterator(Vector *vector, size_t index) { | 
|  | Iterator iterator = { NULL, 0 }; | 
|  |  | 
|  | assert(vector != NULL); | 
|  | assert(index <= vector->size); | 
|  |  | 
|  | if (vector == NULL) return iterator; | 
|  | if (index > vector->size) return iterator; | 
|  | if (vector->element_size == 0) return iterator; | 
|  |  | 
|  | iterator.pointer = _vector_offset(vector, index); | 
|  | iterator.element_size = vector->element_size; | 
|  |  | 
|  | return iterator; | 
|  | } | 
|  |  | 
|  | void *iterator_get(Iterator *iterator) { return iterator->pointer; } | 
|  |  | 
|  | int iterator_erase(Vector *vector, Iterator *iterator) { | 
|  | size_t index = iterator_index(vector, iterator); | 
|  |  | 
|  | if (aom_vector_erase(vector, index) == VECTOR_ERROR) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  |  | 
|  | *iterator = aom_vector_iterator(vector, index); | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | void iterator_increment(Iterator *iterator) { | 
|  | assert(iterator != NULL); | 
|  | // iterator->pointer += iterator->element_size; | 
|  | iterator->pointer = | 
|  | (unsigned char *)iterator->pointer + iterator->element_size; | 
|  | } | 
|  |  | 
|  | void iterator_decrement(Iterator *iterator) { | 
|  | assert(iterator != NULL); | 
|  | // iterator->pointer -= iterator->element_size; | 
|  | iterator->pointer = | 
|  | (unsigned char *)iterator->pointer - iterator->element_size; | 
|  | } | 
|  |  | 
|  | void *iterator_next(Iterator *iterator) { | 
|  | void *current = iterator->pointer; | 
|  | iterator_increment(iterator); | 
|  |  | 
|  | return current; | 
|  | } | 
|  |  | 
|  | void *iterator_previous(Iterator *iterator) { | 
|  | void *current = iterator->pointer; | 
|  | iterator_decrement(iterator); | 
|  |  | 
|  | return current; | 
|  | } | 
|  |  | 
|  | bool iterator_equals(Iterator *first, Iterator *second) { | 
|  | assert(first->element_size == second->element_size); | 
|  | return first->pointer == second->pointer; | 
|  | } | 
|  |  | 
|  | bool iterator_is_before(Iterator *first, Iterator *second) { | 
|  | assert(first->element_size == second->element_size); | 
|  | return first->pointer < second->pointer; | 
|  | } | 
|  |  | 
|  | bool iterator_is_after(Iterator *first, Iterator *second) { | 
|  | assert(first->element_size == second->element_size); | 
|  | return first->pointer > second->pointer; | 
|  | } | 
|  |  | 
|  | size_t iterator_index(Vector *vector, Iterator *iterator) { | 
|  | assert(vector != NULL); | 
|  | assert(iterator != NULL); | 
|  | // return (iterator->pointer - vector->data) / vector->element_size; | 
|  | return ((unsigned char *)iterator->pointer - (unsigned char *)vector->data) / | 
|  | vector->element_size; | 
|  | } | 
|  |  | 
|  | /***** PRIVATE *****/ | 
|  |  | 
|  | bool _vector_should_grow(Vector *vector) { | 
|  | assert(vector->size <= vector->capacity); | 
|  | return vector->size == vector->capacity; | 
|  | } | 
|  |  | 
|  | bool _vector_should_shrink(Vector *vector) { | 
|  | assert(vector->size <= vector->capacity); | 
|  | return vector->size == vector->capacity * VECTOR_SHRINK_THRESHOLD; | 
|  | } | 
|  |  | 
|  | size_t _vector_free_bytes(const Vector *vector) { | 
|  | return aom_vector_free_space(vector) * vector->element_size; | 
|  | } | 
|  |  | 
|  | void *_vector_offset(Vector *vector, size_t index) { | 
|  | // return vector->data + (index * vector->element_size); | 
|  | return (unsigned char *)vector->data + (index * vector->element_size); | 
|  | } | 
|  |  | 
|  | const void *_vector_const_offset(const Vector *vector, size_t index) { | 
|  | // return vector->data + (index * vector->element_size); | 
|  | return (unsigned char *)vector->data + (index * vector->element_size); | 
|  | } | 
|  |  | 
|  | void _vector_assign(Vector *vector, size_t index, void *element) { | 
|  | /* Insert the element */ | 
|  | void *offset = _vector_offset(vector, index); | 
|  | memcpy(offset, element, vector->element_size); | 
|  | } | 
|  |  | 
|  | int _vector_move_right(Vector *vector, size_t index) { | 
|  | assert(vector->size < vector->capacity); | 
|  |  | 
|  | /* The location where to start to move from. */ | 
|  | void *offset = _vector_offset(vector, index); | 
|  |  | 
|  | /* How many to move to the right. */ | 
|  | size_t elements_in_bytes = (vector->size - index) * vector->element_size; | 
|  |  | 
|  | #ifdef __STDC_LIB_EXT1__ | 
|  | size_t right_capacity_in_bytes = | 
|  | (vector->capacity - (index + 1)) * vector->element_size; | 
|  |  | 
|  | /* clang-format off */ | 
|  | int return_code =  memmove_s( | 
|  | offset + vector->element_size, | 
|  | right_capacity_in_bytes, | 
|  | offset, | 
|  | elements_in_bytes); | 
|  |  | 
|  | /* clang-format on */ | 
|  |  | 
|  | return return_code == 0 ? VECTOR_SUCCESS : VECTOR_ERROR; | 
|  |  | 
|  | #else | 
|  | // memmove(offset + vector->element_size, offset, elements_in_bytes); | 
|  | memmove((unsigned char *)offset + vector->element_size, offset, | 
|  | elements_in_bytes); | 
|  | return VECTOR_SUCCESS; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void _vector_move_left(Vector *vector, size_t index) { | 
|  | size_t right_elements_in_bytes; | 
|  | void *offset; | 
|  |  | 
|  | /* The offset into the memory */ | 
|  | offset = _vector_offset(vector, index); | 
|  |  | 
|  | /* How many to move to the left */ | 
|  | right_elements_in_bytes = (vector->size - index - 1) * vector->element_size; | 
|  |  | 
|  | // memmove(offset, offset + vector->element_size, right_elements_in_bytes); | 
|  | memmove(offset, (unsigned char *)offset + vector->element_size, | 
|  | right_elements_in_bytes); | 
|  | } | 
|  |  | 
|  | int _vector_adjust_capacity(Vector *vector) { | 
|  | return _vector_reallocate(vector, | 
|  | MAX(1, vector->size * VECTOR_GROWTH_FACTOR)); | 
|  | } | 
|  |  | 
|  | int _vector_reallocate(Vector *vector, size_t new_capacity) { | 
|  | size_t new_capacity_in_bytes; | 
|  | void *old; | 
|  | assert(vector != NULL); | 
|  |  | 
|  | if (new_capacity < VECTOR_MINIMUM_CAPACITY) { | 
|  | if (vector->capacity > VECTOR_MINIMUM_CAPACITY) { | 
|  | new_capacity = VECTOR_MINIMUM_CAPACITY; | 
|  | } else { | 
|  | /* NO-OP */ | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  | } | 
|  |  | 
|  | new_capacity_in_bytes = new_capacity * vector->element_size; | 
|  | old = vector->data; | 
|  |  | 
|  | if ((vector->data = malloc(new_capacity_in_bytes)) == NULL) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  |  | 
|  | #ifdef __STDC_LIB_EXT1__ | 
|  | /* clang-format off */ | 
|  | if (memcpy_s(vector->data, | 
|  | new_capacity_in_bytes, | 
|  | old, | 
|  | aom_vector_byte_size(vector)) != 0) { | 
|  | return VECTOR_ERROR; | 
|  | } | 
|  | /* clang-format on */ | 
|  | #else | 
|  | memcpy(vector->data, old, aom_vector_byte_size(vector)); | 
|  | #endif | 
|  |  | 
|  | vector->capacity = new_capacity; | 
|  |  | 
|  | free(old); | 
|  |  | 
|  | return VECTOR_SUCCESS; | 
|  | } | 
|  |  | 
|  | void _vector_swap(size_t *first, size_t *second) { | 
|  | size_t temp = *first; | 
|  | *first = *second; | 
|  | *second = temp; | 
|  | } |