LCOV - code coverage report
Current view: top level - lib - lwan-array.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 36 50 72.0 %
Date: 2023-04-18 16:19:03 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /*
       2             :  * lwan - web server
       3             :  * Copyright (c) 2017 L. A. F. Pereira <l@tia.mat.br>
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU General Public License
       7             :  * as published by the Free Software Foundation; either version 2
       8             :  * of the License, or any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
      18             :  * USA.
      19             :  */
      20             : 
      21             : #define _DEFAULT_SOURCE
      22             : #define _GNU_SOURCE
      23             : #include <errno.h>
      24             : #include <stdint.h>
      25             : #include <stdlib.h>
      26             : 
      27             : #include "lwan.h"
      28             : #include "lwan-array.h"
      29             : 
      30         992 : int lwan_array_reset(struct lwan_array *a, void *inline_storage)
      31             : {
      32         992 :     if (UNLIKELY(!a))
      33           0 :         return -EINVAL;
      34             : 
      35         992 :     if (a->base != inline_storage)
      36         753 :         free(a->base);
      37             : 
      38         992 :     a->base = NULL;
      39         992 :     a->elements = 0;
      40             : 
      41         992 :     return 0;
      42             : }
      43             : 
      44             : #if !defined(LWAN_HAVE_BUILTIN_ADD_OVERFLOW)
      45             : static inline bool add_overflow(size_t a, size_t b, size_t *out)
      46             : {
      47             :     if (UNLIKELY(a > 0 && b > SIZE_MAX - a))
      48             :         return true;
      49             : 
      50             :     *out = a + b;
      51             :     return false;
      52             : }
      53             : #else
      54             : #define add_overflow __builtin_add_overflow
      55             : #endif
      56             : 
      57        8380 : void *lwan_array_append_heap(struct lwan_array *a, size_t element_size)
      58             : {
      59        8380 :     if (!(a->elements % LWAN_ARRAY_INCREMENT)) {
      60             :         void *new_base;
      61             :         size_t new_cap;
      62             : 
      63        1302 :         if (UNLIKELY(
      64             :                 add_overflow(a->elements, LWAN_ARRAY_INCREMENT, &new_cap))) {
      65           0 :             errno = EOVERFLOW;
      66           0 :             return NULL;
      67             :         }
      68             : 
      69        1302 :         new_base = reallocarray(a->base, new_cap, element_size);
      70        1302 :         if (UNLIKELY(!new_base))
      71           0 :             return NULL;
      72             : 
      73        1302 :         a->base = new_base;
      74             :     }
      75             : 
      76        8380 :     return ((char *)a->base) + a->elements++ * element_size;
      77             : }
      78             : 
      79         854 : void *lwan_array_append_inline(struct lwan_array *a,
      80             :                                size_t element_size,
      81             :                                void *inline_storage)
      82             : {
      83         854 :     if (!a->base)
      84         334 :         a->base = inline_storage;
      85         520 :     else if (UNLIKELY(a->base != inline_storage))
      86           0 :         return lwan_array_append_heap(a, element_size);
      87             : 
      88         854 :     assert(a->elements <= LWAN_ARRAY_INCREMENT);
      89             : 
      90         854 :     if (a->elements == LWAN_ARRAY_INCREMENT) {
      91             :         void *new_base =
      92           0 :             reallocarray(NULL, 2 * LWAN_ARRAY_INCREMENT, element_size);
      93             : 
      94           0 :         if (UNLIKELY(!new_base))
      95           0 :             return NULL;
      96             : 
      97           0 :         a->base = memcpy(new_base, inline_storage,
      98             :                          LWAN_ARRAY_INCREMENT * element_size);
      99             :     }
     100             : 
     101         854 :     return ((char *)a->base) + a->elements++ * element_size;
     102             : }
     103             : 
     104         324 : void lwan_array_sort(struct lwan_array *a,
     105             :                      size_t element_size,
     106             :                      int (*cmp)(const void *a, const void *b))
     107             : {
     108         324 :     if (LIKELY(a->elements))
     109         324 :         qsort(a->base, a->elements, element_size, cmp);
     110         324 : }
     111             : 
     112           2 : static void coro_lwan_array_free_heap(void *data)
     113             : {
     114           2 :     struct lwan_array *array = data;
     115             : 
     116           2 :     lwan_array_reset(array, NULL);
     117           2 :     free(array);
     118           2 : }
     119             : 
     120           0 : static void coro_lwan_array_free_inline(void *data)
     121             : {
     122           0 :     struct lwan_array *array = data;
     123             : 
     124           0 :     lwan_array_reset(array, array + 1);
     125           0 :     free(array);
     126           0 : }
     127             : 
     128           2 : struct lwan_array *coro_lwan_array_new(struct coro *coro,
     129             :                                        size_t struct_size,
     130             :                                        bool inline_first)
     131             : {
     132             :     struct lwan_array *array;
     133             : 
     134           2 :     assert(struct_size >= sizeof(struct lwan_array));
     135             : 
     136           2 :     array = coro_malloc_full(coro, struct_size,
     137             :                              inline_first ? coro_lwan_array_free_inline
     138             :                                           : coro_lwan_array_free_heap);
     139           2 :     if (LIKELY(array))
     140           2 :         *array = (struct lwan_array){.base = NULL, .elements = 0};
     141             : 
     142           2 :     return array;
     143             : }

Generated by: LCOV version 1.15-2-gb9d6727