LCOV - code coverage report
Current view: top level - src/plugins/mmapstorage - dynarray.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 44 44 100.0 %
Date: 2019-09-12 12:28:41 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for DynArray, a simple dynamic array for meta-key deduplication.
       5             :  *
       6             :  * The DynArray is used to store pointers of meta-keys. The dynArrayFindOrInsert function
       7             :  * searches for a pointer in the structure. If it is not yet in the array, it will be inserted.
       8             :  * If the underlying array is too small, it is resized such that it can accomodate further elements.
       9             :  * The dynArrayFind function only searches for elements.
      10             :  *
      11             :  * The mmapstorage plugin uses the DynArray to deduplicate meta-keys.
      12             :  *
      13             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
      14             :  *
      15             :  */
      16             : 
      17             : #include "dynarray.h"
      18             : 
      19             : #include <kdblogger.h>
      20             : 
      21             : /* -- DynArray Implementation ----------------------------------------------------------------------------------------------------------- */
      22             : 
      23             : #define ELEKTRA_MMAP_DYNARRAY_MINSIZE (8)
      24             : 
      25             : /**
      26             :  * @brief Allocator for DynArray.
      27             :  *
      28             :  * @return newly allocated DynArray
      29             :  */
      30         346 : DynArray * ELEKTRA_PLUGIN_FUNCTION (dynArrayNew) (void)
      31             : {
      32         346 :         DynArray * dynArray = elektraCalloc (sizeof (DynArray));
      33         346 :         dynArray->keyArray = elektraCalloc (sizeof (Key *) * ELEKTRA_MMAP_DYNARRAY_MINSIZE);
      34         346 :         dynArray->mappedKeyArray = 0;
      35         346 :         dynArray->size = 0;
      36         346 :         dynArray->alloc = ELEKTRA_MMAP_DYNARRAY_MINSIZE;
      37         346 :         return dynArray;
      38             : }
      39             : 
      40             : /**
      41             :  * @brief Deallocator for DynArray.
      42             :  *
      43             :  * @param dynArray to be free()'d
      44             :  */
      45         348 : void ELEKTRA_PLUGIN_FUNCTION (dynArrayDelete) (DynArray * dynArray)
      46             : {
      47         348 :         if (!dynArray)
      48             :         {
      49             :                 return;
      50             :         }
      51         346 :         if (dynArray->keyArray)
      52             :         {
      53         346 :                 elektraFree (dynArray->keyArray);
      54             :         }
      55         346 :         if (dynArray->mappedKeyArray)
      56             :         {
      57          97 :                 elektraFree (dynArray->mappedKeyArray);
      58             :         }
      59         346 :         elektraFree (dynArray);
      60             : }
      61             : 
      62             : /**
      63             :  * @brief Find position or insert Key pointer into DynArray.
      64             :  *
      65             :  * @param key to be found or inserted
      66             :  * @param dynArray where the key should be searched for or inserted
      67             :  *
      68             :  * @retval -1 on memory error (malloc failed), or size exceeded
      69             :  * @retval 0 if the key was inserted
      70             :  * @retval 1 if the key was found
      71             :  */
      72         505 : int ELEKTRA_PLUGIN_FUNCTION (dynArrayFindOrInsert) (Key * key, DynArray * dynArray)
      73             : {
      74         505 :         size_t l = 0;
      75         505 :         size_t h = dynArray->size;
      76             :         ELEKTRA_LOG_DEBUG ("l: %zu", l);
      77             :         ELEKTRA_LOG_DEBUG ("h: %zu", h);
      78             :         ELEKTRA_LOG_DEBUG ("dynArray->size: %zu", dynArray->size);
      79             :         ELEKTRA_LOG_DEBUG ("dynArray->alloc: %zu", dynArray->alloc);
      80             : 
      81        2392 :         while (l < h)
      82             :         {
      83        1386 :                 size_t m = (l + h) >> 1;
      84             :                 ELEKTRA_LOG_DEBUG ("m: %zu", m);
      85             : 
      86        1386 :                 if (dynArray->keyArray[m] > key)
      87             :                 {
      88             :                         h = m;
      89             :                 }
      90         554 :                 else if (dynArray->keyArray[m] < key)
      91             :                 {
      92         550 :                         l = ++m;
      93             :                 }
      94             :                 else
      95             :                 {
      96             :                         return 1; // found
      97             :                 }
      98             :         }
      99             :         // insert key at index l
     100         501 :         if (dynArray->size == dynArray->alloc)
     101             :         {
     102             :                 // doubling the array size to keep reallocations logarithmic
     103           8 :                 size_t oldAllocSize = dynArray->alloc;
     104           8 :                 if (oldAllocSize > (SIZE_MAX / 2))
     105             :                 {
     106             :                         return -1; // error
     107             :                 }
     108           8 :                 Key ** new = elektraCalloc ((2 * oldAllocSize) * sizeof (Key *));
     109           8 :                 memcpy (new, dynArray->keyArray, dynArray->size * sizeof (Key *));
     110           8 :                 elektraFree (dynArray->keyArray);
     111           8 :                 dynArray->keyArray = new;
     112           8 :                 dynArray->alloc = 2 * oldAllocSize;
     113             :         }
     114             : 
     115         501 :         memmove ((void *) (dynArray->keyArray + l + 1), (void *) (dynArray->keyArray + l), ((dynArray->size) - l) * (sizeof (size_t)));
     116         501 :         dynArray->keyArray[l] = key;
     117         501 :         dynArray->size += 1;
     118             : 
     119         501 :         return 0; // inserted
     120             : }
     121             : 
     122             : /**
     123             :  * @brief Find Key pointer in the DynArray.
     124             :  *
     125             :  * @param key Key pointer to search for
     126             :  * @param dynArray where the Key should be searched for
     127             :  *
     128             :  * @return position of the Key pointer in the DynArray, or -1 if not found or size exceeded
     129             :  */
     130         305 : ssize_t ELEKTRA_PLUGIN_FUNCTION (dynArrayFind) (Key * key, DynArray * dynArray)
     131             : {
     132         305 :         size_t l = 0;
     133         305 :         size_t h = dynArray->size;
     134             :         ELEKTRA_LOG_DEBUG ("l: %zu", l);
     135             :         ELEKTRA_LOG_DEBUG ("h: %zu", h);
     136             :         ELEKTRA_LOG_DEBUG ("dynArray->size: %zu", dynArray->size);
     137             :         ELEKTRA_LOG_DEBUG ("dynArray->alloc: %zu", dynArray->alloc);
     138             : 
     139         850 :         while (l < h)
     140             :         {
     141         545 :                 size_t m = (l + h) >> 1;
     142             :                 ELEKTRA_LOG_DEBUG ("m: %zu", m);
     143             : 
     144         545 :                 if (dynArray->keyArray[m] > key)
     145             :                 {
     146             :                         h = m;
     147             :                 }
     148         399 :                 else if (dynArray->keyArray[m] < key)
     149             :                 {
     150          94 :                         l = ++m;
     151             :                 }
     152             :                 else
     153             :                 {
     154         305 :                         if (m < SSIZE_MAX)
     155             :                         {
     156         305 :                                 return m; // found
     157             :                         }
     158             :                         else
     159             :                         {
     160             :                                 return -1;
     161             :                         }
     162             :                 }
     163             :         }
     164             : 
     165             :         return -1;
     166             : }

Generated by: LCOV version 1.13