LCOV - code coverage report
Current view: top level - Codec - vector.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 269 0.0 %
Date: 2019-11-25 17:12:20 Functions: 0 50 0.0 %

          Line data    Source code
       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 "vector.h"
      30             : #define MAX(a, b) ((a) > (b) ? (a) : (b))
      31           0 : int eb_aom_vector_setup(Vector *vector, size_t capacity, size_t element_size) {
      32           0 :   assert(vector != NULL);
      33             : 
      34           0 :   if (vector == NULL) return VECTOR_ERROR;
      35             : 
      36           0 :   vector->size = 0;
      37           0 :   vector->capacity = MAX(VECTOR_MINIMUM_CAPACITY, capacity);
      38           0 :   vector->element_size = element_size;
      39           0 :   vector->data = malloc(vector->capacity * element_size);
      40             : 
      41           0 :   return vector->data == NULL ? VECTOR_ERROR : VECTOR_SUCCESS;
      42             : }
      43             : 
      44           0 : int eb_aom_vector_copy(Vector *destination, Vector *source) {
      45           0 :   assert(destination != NULL);
      46           0 :   assert(source != NULL);
      47           0 :   assert(eb_aom_vector_is_initialized(source));
      48           0 :   assert(!eb_aom_vector_is_initialized(destination));
      49             : 
      50           0 :   if (destination == NULL) return VECTOR_ERROR;
      51           0 :   if (source == NULL) return VECTOR_ERROR;
      52           0 :   if (eb_aom_vector_is_initialized(destination)) return VECTOR_ERROR;
      53           0 :   if (!eb_aom_vector_is_initialized(source)) return VECTOR_ERROR;
      54             : 
      55             :   /* Copy ALL the data */
      56           0 :   destination->size = source->size;
      57           0 :   destination->capacity = source->size * 2;
      58           0 :   destination->element_size = source->element_size;
      59             : 
      60             :   /* Note that we are not necessarily allocating the same capacity */
      61           0 :   destination->data = malloc(destination->capacity * source->element_size);
      62           0 :   if (destination->data == NULL) return VECTOR_ERROR;
      63             : 
      64           0 :   memcpy(destination->data, source->data, eb_aom_vector_byte_size(source));
      65             : 
      66           0 :   return VECTOR_SUCCESS;
      67             : }
      68             : 
      69           0 : int eb_aom_vector_copy_assign(Vector *destination, Vector *source) {
      70           0 :   assert(destination != NULL);
      71           0 :   assert(source != NULL);
      72           0 :   assert(eb_aom_vector_is_initialized(source));
      73           0 :   assert(eb_aom_vector_is_initialized(destination));
      74             : 
      75           0 :   if (destination == NULL) return VECTOR_ERROR;
      76           0 :   if (source == NULL) return VECTOR_ERROR;
      77           0 :   if (!eb_aom_vector_is_initialized(destination)) return VECTOR_ERROR;
      78           0 :   if (!eb_aom_vector_is_initialized(source)) return VECTOR_ERROR;
      79             : 
      80           0 :   eb_aom_vector_destroy(destination);
      81             : 
      82           0 :   return eb_aom_vector_copy(destination, source);
      83             : }
      84             : 
      85           0 : int eb_aom_vector_move(Vector *destination, Vector *source) {
      86           0 :   assert(destination != NULL);
      87           0 :   assert(source != NULL);
      88             : 
      89           0 :   if (destination == NULL) return VECTOR_ERROR;
      90           0 :   if (source == NULL) return VECTOR_ERROR;
      91             : 
      92           0 :   *destination = *source;
      93           0 :   source->data = NULL;
      94             : 
      95           0 :   return VECTOR_SUCCESS;
      96             : }
      97             : 
      98           0 : int eb_aom_vector_move_assign(Vector *destination, Vector *source) {
      99           0 :   eb_aom_vector_swap(destination, source);
     100           0 :   return eb_aom_vector_destroy(source);
     101             : }
     102             : 
     103           0 : int eb_aom_vector_swap(Vector *destination, Vector *source) {
     104             :   void *temp;
     105             : 
     106           0 :   assert(destination != NULL);
     107           0 :   assert(source != NULL);
     108           0 :   assert(eb_aom_vector_is_initialized(source));
     109           0 :   assert(eb_aom_vector_is_initialized(destination));
     110             : 
     111           0 :   if (destination == NULL) return VECTOR_ERROR;
     112           0 :   if (source == NULL) return VECTOR_ERROR;
     113           0 :   if (!eb_aom_vector_is_initialized(destination)) return VECTOR_ERROR;
     114           0 :   if (!eb_aom_vector_is_initialized(source)) return VECTOR_ERROR;
     115             : 
     116           0 :   _vector_swap(&destination->size, &source->size);
     117           0 :   _vector_swap(&destination->capacity, &source->capacity);
     118           0 :   _vector_swap(&destination->element_size, &source->element_size);
     119             : 
     120           0 :   temp = destination->data;
     121           0 :   destination->data = source->data;
     122           0 :   source->data = temp;
     123             : 
     124           0 :   return VECTOR_SUCCESS;
     125             : }
     126             : 
     127           0 : int eb_aom_vector_destroy(Vector *vector) {
     128           0 :   assert(vector != NULL);
     129             : 
     130           0 :   if (vector == NULL) return VECTOR_ERROR;
     131             : 
     132           0 :   free(vector->data);
     133           0 :   vector->data = NULL;
     134             : 
     135           0 :   return VECTOR_SUCCESS;
     136             : }
     137             : 
     138             : /* Insertion */
     139           0 : int eb_aom_vector_push_back(Vector *vector, void *element) {
     140           0 :   assert(vector != NULL);
     141           0 :   assert(element != NULL);
     142             : 
     143           0 :   if (_vector_should_grow(vector)) {
     144           0 :     if (_vector_adjust_capacity(vector) == VECTOR_ERROR)
     145           0 :       return VECTOR_ERROR;
     146             :   }
     147             : 
     148           0 :   _vector_assign(vector, vector->size, element);
     149             : 
     150           0 :   ++vector->size;
     151             : 
     152           0 :   return VECTOR_SUCCESS;
     153             : }
     154             : 
     155           0 : int eb_aom_vector_push_front(Vector *vector, void *element) {
     156           0 :   return eb_aom_vector_insert(vector, 0, element);
     157             : }
     158             : 
     159           0 : int eb_aom_vector_insert(Vector *vector, size_t index, void *element) {
     160             :   void *offset;
     161             : 
     162           0 :   assert(vector != NULL);
     163           0 :   assert(element != NULL);
     164           0 :   assert(index <= vector->size);
     165             : 
     166           0 :   if (vector == NULL) return VECTOR_ERROR;
     167           0 :   if (element == NULL) return VECTOR_ERROR;
     168           0 :   if (vector->element_size == 0) return VECTOR_ERROR;
     169           0 :   if (index > vector->size) return VECTOR_ERROR;
     170             : 
     171           0 :   if (_vector_should_grow(vector)) {
     172           0 :     if (_vector_adjust_capacity(vector) == VECTOR_ERROR)
     173           0 :       return VECTOR_ERROR;
     174             :   }
     175             : 
     176             :   /* Move other elements to the right */
     177           0 :   if (_vector_move_right(vector, index) == VECTOR_ERROR)
     178           0 :     return VECTOR_ERROR;
     179             :   /* Insert the element */
     180           0 :   offset = _vector_offset(vector, index);
     181           0 :   memcpy(offset, element, vector->element_size);
     182           0 :   ++vector->size;
     183             : 
     184           0 :   return VECTOR_SUCCESS;
     185             : }
     186             : 
     187           0 : int eb_aom_vector_assign(Vector *vector, size_t index, void *element) {
     188           0 :   assert(vector != NULL);
     189           0 :   assert(element != NULL);
     190           0 :   assert(index < vector->size);
     191             : 
     192           0 :   if (vector == NULL) return VECTOR_ERROR;
     193           0 :   if (element == NULL) return VECTOR_ERROR;
     194           0 :   if (vector->element_size == 0) return VECTOR_ERROR;
     195           0 :   if (index >= vector->size) return VECTOR_ERROR;
     196             : 
     197           0 :   _vector_assign(vector, index, element);
     198             : 
     199           0 :   return VECTOR_SUCCESS;
     200             : }
     201             : 
     202             : /* Deletion */
     203           0 : int eb_aom_vector_pop_back(Vector *vector) {
     204           0 :   assert(vector != NULL);
     205           0 :   assert(vector->size > 0);
     206             : 
     207           0 :   if (vector == NULL) return VECTOR_ERROR;
     208           0 :   if (vector->element_size == 0) return VECTOR_ERROR;
     209             : 
     210           0 :   --vector->size;
     211             : 
     212             : #ifndef VECTOR_NO_SHRINK
     213           0 :   if (_vector_should_shrink(vector))
     214           0 :     _vector_adjust_capacity(vector);
     215             : #endif
     216             : 
     217           0 :   return VECTOR_SUCCESS;
     218             : }
     219             : 
     220           0 : int eb_aom_vector_pop_front(Vector *vector) { return eb_aom_vector_erase(vector, 0); }
     221             : 
     222           0 : int eb_aom_vector_erase(Vector *vector, size_t index) {
     223           0 :   assert(vector != NULL);
     224           0 :   assert(index < vector->size);
     225             : 
     226           0 :   if (vector == NULL) return VECTOR_ERROR;
     227           0 :   if (vector->element_size == 0) return VECTOR_ERROR;
     228           0 :   if (index >= vector->size) return VECTOR_ERROR;
     229             : 
     230             :   /* Just overwrite */
     231           0 :   _vector_move_left(vector, index);
     232             : 
     233             : #ifndef VECTOR_NO_SHRINK
     234           0 :   if (--vector->size == vector->capacity / 4)
     235           0 :     _vector_adjust_capacity(vector);
     236             : #endif
     237             : 
     238           0 :   return VECTOR_SUCCESS;
     239             : }
     240             : 
     241           0 : int eb_aom_vector_clear(Vector *vector) { return eb_aom_vector_resize(vector, 0); }
     242             : 
     243             : /* Lookup */
     244           0 : void *eb_aom_vector_get(Vector *vector, size_t index) {
     245           0 :   assert(vector != NULL);
     246           0 :   assert(index < vector->size);
     247             : 
     248           0 :   if (vector == NULL) return NULL;
     249           0 :   if (vector->element_size == 0) return NULL;
     250           0 :   if (index >= vector->size) return NULL;
     251             : 
     252           0 :   return _vector_offset(vector, index);
     253             : }
     254             : 
     255           0 : const void *eb_aom_vector_const_get(const Vector *vector, size_t index) {
     256           0 :   assert(vector != NULL);
     257           0 :   assert(index < vector->size);
     258             : 
     259           0 :   if (vector == NULL) return NULL;
     260           0 :   if (vector->element_size == 0) return NULL;
     261           0 :   if (index >= vector->size) return NULL;
     262             : 
     263           0 :   return _vector_const_offset(vector, index);
     264             : }
     265             : 
     266           0 : void *eb_aom_vector_front(Vector *vector) { return eb_aom_vector_get(vector, 0); }
     267             : 
     268           0 : void *eb_aom_vector_back(Vector *vector) {
     269           0 :   return eb_aom_vector_get(vector, vector->size - 1);
     270             : }
     271             : 
     272             : /* Information */
     273             : 
     274           0 : bool eb_aom_vector_is_initialized(const Vector *vector) {
     275           0 :   return vector->data != NULL;
     276             : }
     277             : 
     278           0 : size_t eb_aom_vector_byte_size(const Vector *vector) {
     279           0 :   return vector->size * vector->element_size;
     280             : }
     281             : 
     282           0 : size_t eb_aom_vector_free_space(const Vector *vector) {
     283           0 :   return vector->capacity - vector->size;
     284             : }
     285             : 
     286           0 : bool eb_aom_vector_is_empty(const Vector *vector) { return vector->size == 0; }
     287             : 
     288             : /* Memory management */
     289           0 : int eb_aom_vector_resize(Vector *vector, size_t new_size) {
     290           0 :   if (new_size <= vector->capacity * VECTOR_SHRINK_THRESHOLD) {
     291           0 :     vector->size = new_size;
     292           0 :     if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1)
     293           0 :       return VECTOR_ERROR;
     294           0 :   } else if (new_size > vector->capacity) {
     295           0 :     if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1)
     296           0 :       return VECTOR_ERROR;
     297             :   }
     298             : 
     299           0 :   vector->size = new_size;
     300             : 
     301           0 :   return VECTOR_SUCCESS;
     302             : }
     303             : 
     304           0 : int eb_aom_vector_reserve(Vector *vector, size_t minimum_capacity) {
     305           0 :   if (minimum_capacity > vector->capacity) {
     306           0 :     if (_vector_reallocate(vector, minimum_capacity) == VECTOR_ERROR)
     307           0 :       return VECTOR_ERROR;
     308             :   }
     309             : 
     310           0 :   return VECTOR_SUCCESS;
     311             : }
     312             : 
     313           0 : int eb_aom_vector_shrink_to_fit(Vector *vector) {
     314           0 :   return _vector_reallocate(vector, vector->size);
     315             : }
     316             : 
     317             : /* Iterators */
     318           0 : Iterator eb_aom_vector_begin(Vector *vector) { return eb_aom_vector_iterator(vector, 0); }
     319             : 
     320           0 : Iterator eb_aom_vector_end(Vector *vector) {
     321           0 :   return eb_aom_vector_iterator(vector, vector->size);
     322             : }
     323             : 
     324           0 : Iterator eb_aom_vector_iterator(Vector *vector, size_t index) {
     325           0 :   Iterator iterator = { NULL, 0 };
     326             : 
     327           0 :   assert(vector != NULL);
     328           0 :   assert(index <= vector->size);
     329             : 
     330           0 :   if (vector == NULL) return iterator;
     331           0 :   if (index > vector->size) return iterator;
     332           0 :   if (vector->element_size == 0) return iterator;
     333             : 
     334           0 :   iterator.pointer = _vector_offset(vector, index);
     335           0 :   iterator.element_size = vector->element_size;
     336             : 
     337           0 :   return iterator;
     338             : }
     339             : 
     340           0 : void *iterator_get(Iterator *iterator) { return iterator->pointer; }
     341             : 
     342           0 : int iterator_erase(Vector *vector, Iterator *iterator) {
     343           0 :   size_t index = iterator_index(vector, iterator);
     344             : 
     345           0 :   if (eb_aom_vector_erase(vector, index) == VECTOR_ERROR)
     346           0 :     return VECTOR_ERROR;
     347           0 :   *iterator = eb_aom_vector_iterator(vector, index);
     348             : 
     349           0 :   return VECTOR_SUCCESS;
     350             : }
     351             : 
     352           0 : void iterator_increment(Iterator *iterator) {
     353           0 :   assert(iterator != NULL);
     354             :   // iterator->pointer += iterator->element_size;
     355           0 :   iterator->pointer =
     356           0 :       (unsigned char *)iterator->pointer + iterator->element_size;
     357           0 : }
     358             : 
     359           0 : void iterator_decrement(Iterator *iterator) {
     360           0 :   assert(iterator != NULL);
     361             :   // iterator->pointer -= iterator->element_size;
     362           0 :   iterator->pointer =
     363           0 :       (unsigned char *)iterator->pointer - iterator->element_size;
     364           0 : }
     365             : 
     366           0 : void *iterator_next(Iterator *iterator) {
     367           0 :   void *current = iterator->pointer;
     368           0 :   iterator_increment(iterator);
     369             : 
     370           0 :   return current;
     371             : }
     372             : 
     373           0 : void *iterator_previous(Iterator *iterator) {
     374           0 :   void *current = iterator->pointer;
     375           0 :   iterator_decrement(iterator);
     376             : 
     377           0 :   return current;
     378             : }
     379             : 
     380           0 : bool iterator_equals(Iterator *first, Iterator *second) {
     381           0 :   assert(first->element_size == second->element_size);
     382           0 :   return first->pointer == second->pointer;
     383             : }
     384             : 
     385           0 : bool iterator_is_before(Iterator *first, Iterator *second) {
     386           0 :   assert(first->element_size == second->element_size);
     387           0 :   return first->pointer < second->pointer;
     388             : }
     389             : 
     390           0 : bool iterator_is_after(Iterator *first, Iterator *second) {
     391           0 :   assert(first->element_size == second->element_size);
     392           0 :   return first->pointer > second->pointer;
     393             : }
     394             : 
     395           0 : size_t iterator_index(Vector *vector, Iterator *iterator) {
     396           0 :   assert(vector != NULL);
     397           0 :   assert(iterator != NULL);
     398             :   // return (iterator->pointer - vector->data) / vector->element_size;
     399           0 :   return ((unsigned char *)iterator->pointer - (unsigned char *)vector->data) /
     400           0 :          vector->element_size;
     401             : }
     402             : 
     403             : /***** PRIVATE *****/
     404             : 
     405           0 : bool _vector_should_grow(Vector *vector) {
     406           0 :   assert(vector->size <= vector->capacity);
     407           0 :   return vector->size == vector->capacity;
     408             : }
     409             : 
     410           0 : bool _vector_should_shrink(Vector *vector) {
     411           0 :   assert(vector->size <= vector->capacity);
     412           0 :   return vector->size == vector->capacity * VECTOR_SHRINK_THRESHOLD;
     413             : }
     414             : 
     415           0 : size_t _vector_free_bytes(const Vector *vector) {
     416           0 :   return eb_aom_vector_free_space(vector) * vector->element_size;
     417             : }
     418             : 
     419           0 : void *_vector_offset(Vector *vector, size_t index) {
     420             :   // return vector->data + (index * vector->element_size);
     421           0 :   return (unsigned char *)vector->data + (index * vector->element_size);
     422             : }
     423             : 
     424           0 : const void *_vector_const_offset(const Vector *vector, size_t index) {
     425             :   // return vector->data + (index * vector->element_size);
     426           0 :   return (unsigned char *)vector->data + (index * vector->element_size);
     427             : }
     428             : 
     429           0 : void _vector_assign(Vector *vector, size_t index, void *element) {
     430             :   /* Insert the element */
     431           0 :   void *offset = _vector_offset(vector, index);
     432           0 :   memcpy(offset, element, vector->element_size);
     433           0 : }
     434             : 
     435           0 : int _vector_move_right(Vector *vector, size_t index) {
     436           0 :   assert(vector->size < vector->capacity);
     437             : 
     438             :   /* The location where to start to move from. */
     439           0 :   void *offset = _vector_offset(vector, index);
     440             : 
     441             :   /* How many to move to the right. */
     442           0 :   size_t elements_in_bytes = (vector->size - index) * vector->element_size;
     443             : 
     444             : #ifdef __STDC_LIB_EXT1__
     445             :   size_t right_capacity_in_bytes =
     446             :       (vector->capacity - (index + 1)) * vector->element_size;
     447             : 
     448             :   /* clang-format off */
     449             :     int return_code =  memmove_s(
     450             :         offset + vector->element_size,
     451             :         right_capacity_in_bytes,
     452             :         offset,
     453             :         elements_in_bytes);
     454             : 
     455             :   /* clang-format on */
     456             : 
     457             :   return return_code == 0 ? VECTOR_SUCCESS : VECTOR_ERROR;
     458             : 
     459             : #else
     460             :   // memmove(offset + vector->element_size, offset, elements_in_bytes);
     461           0 :   memmove((unsigned char *)offset + vector->element_size, offset,
     462             :           elements_in_bytes);
     463           0 :   return VECTOR_SUCCESS;
     464             : #endif
     465             : }
     466             : 
     467           0 : void _vector_move_left(Vector *vector, size_t index) {
     468             :   size_t right_elements_in_bytes;
     469             :   void *offset;
     470             : 
     471             :   /* The offset into the memory */
     472           0 :   offset = _vector_offset(vector, index);
     473             : 
     474             :   /* How many to move to the left */
     475           0 :   right_elements_in_bytes = (vector->size - index - 1) * vector->element_size;
     476             : 
     477             :   // memmove(offset, offset + vector->element_size, right_elements_in_bytes);
     478           0 :   memmove(offset, (unsigned char *)offset + vector->element_size,
     479             :           right_elements_in_bytes);
     480           0 : }
     481             : 
     482           0 : int _vector_adjust_capacity(Vector *vector) {
     483           0 :   return _vector_reallocate(vector,
     484           0 :                             MAX(1, vector->size * VECTOR_GROWTH_FACTOR));
     485             : }
     486             : 
     487           0 : int _vector_reallocate(Vector *vector, size_t new_capacity) {
     488             :   size_t new_capacity_in_bytes;
     489             :   void *old;
     490           0 :   assert(vector != NULL);
     491             : 
     492           0 :   if (new_capacity < VECTOR_MINIMUM_CAPACITY) {
     493           0 :     if (vector->capacity > VECTOR_MINIMUM_CAPACITY) {
     494           0 :       new_capacity = VECTOR_MINIMUM_CAPACITY;
     495             :     } else {
     496             :       /* NO-OP */
     497           0 :       return VECTOR_SUCCESS;
     498             :     }
     499             :   }
     500             : 
     501           0 :   new_capacity_in_bytes = new_capacity * vector->element_size;
     502           0 :   old = vector->data;
     503             : 
     504           0 :   if ((vector->data = malloc(new_capacity_in_bytes)) == NULL)
     505           0 :     return VECTOR_ERROR;
     506             : #ifdef __STDC_LIB_EXT1__
     507             :   /* clang-format off */
     508             :     if (memcpy_s(vector->data,
     509             :                              new_capacity_in_bytes,
     510             :                              old,
     511             :                              eb_aom_vector_byte_size(vector)) != 0) {
     512             :         return VECTOR_ERROR;
     513             :     }
     514             : /* clang-format on */
     515             : #else
     516           0 :   memcpy(vector->data, old, eb_aom_vector_byte_size(vector));
     517             : #endif
     518             : 
     519           0 :   vector->capacity = new_capacity;
     520             : 
     521           0 :   free(old);
     522             : 
     523           0 :   return VECTOR_SUCCESS;
     524             : }
     525             : 
     526           0 : void _vector_swap(size_t *first, size_t *second) {
     527           0 :   size_t temp = *first;
     528           0 :   *first = *second;
     529           0 :   *second = temp;
     530           0 : }

Generated by: LCOV version 1.14