back to topotato report
topotato coverage report
Current view: top level - lib - darr.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 1 51 2.0 %
Date: 2023-11-16 17:19:14 Functions: 2 9 22.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * June 23 2023, Christian Hopps <chopps@labn.net>
       4             :  *
       5             :  * Copyright (c) 2023, LabN Consulting, L.L.C.
       6             :  *
       7             :  */
       8             : #include <zebra.h>
       9             : #include "darr.h"
      10             : #include "memory.h"
      11             : 
      12          12 : DEFINE_MTYPE(LIB, DARR, "Dynamic Array");
      13             : 
      14             : static uint _msb(uint count)
      15             : {
      16             :         uint bit = 0;
      17             :         int msb = 0;
      18             : 
      19           0 :         while (count) {
      20           0 :                 if (count & 1)
      21           0 :                         msb = bit;
      22           0 :                 count >>= 1;
      23           0 :                 bit += 1;
      24             :         }
      25           0 :         return msb;
      26             : }
      27             : 
      28           0 : static uint darr_next_count(uint count, size_t esize)
      29             : {
      30           0 :         uint ncount;
      31             : 
      32           0 :         if (esize > sizeof(long long) && count == 1)
      33             :                 /* treat like a pointer */
      34             :                 ncount = 1;
      35             :         else {
      36           0 :                 uint msb = _msb(count);
      37             : 
      38           0 :                 ncount = 1ull << msb;
      39             :                 /* if the users count wasn't a pow2 make it the next pow2. */
      40           0 :                 if (ncount != count) {
      41           0 :                         assert(ncount < count);
      42           0 :                         ncount <<= 1;
      43           0 :                         if (esize < sizeof(long long) && ncount < 8)
      44           0 :                                 ncount = 8;
      45             :                 }
      46             :         }
      47           0 :         return ncount;
      48             : }
      49             : 
      50           0 : static size_t darr_size(uint count, size_t esize)
      51             : {
      52           0 :         return count * esize + sizeof(struct darr_metadata);
      53             : }
      54             : 
      55           0 : void *__darr_resize(void *a, uint count, size_t esize)
      56             : {
      57           0 :         uint ncount = darr_next_count(count, esize);
      58           0 :         size_t osz = (a == NULL) ? 0 : darr_size(darr_cap(a), esize);
      59           0 :         size_t sz = darr_size(ncount, esize);
      60           0 :         struct darr_metadata *dm = XREALLOC(MTYPE_DARR,
      61             :                                             a ? _darr_meta(a) : NULL, sz);
      62             : 
      63           0 :         if (sz > osz)
      64           0 :                 memset((char *)dm + osz, 0, sz - osz);
      65           0 :         dm->cap = ncount;
      66           0 :         return (void *)(dm + 1);
      67             : }
      68             : 
      69             : 
      70           0 : void *__darr_insert_n(void *a, uint at, uint count, size_t esize, bool zero)
      71             : {
      72             : 
      73           0 :         struct darr_metadata *dm;
      74           0 :         uint olen, nlen;
      75             : 
      76           0 :         if (!a)
      77           0 :                 a = __darr_resize(NULL, at + count, esize);
      78           0 :         dm = (struct darr_metadata *)a - 1;
      79           0 :         olen = dm->len;
      80             : 
      81             :         // at == 1
      82             :         // count == 100
      83             :         // olen == 2
      84             : 
      85             :         /* see if the user is expanding first using `at` */
      86           0 :         if (at >= olen)
      87           0 :                 nlen = at + count;
      88             :         else
      89           0 :                 nlen = olen + count;
      90             : 
      91           0 :         if (nlen > dm->cap) {
      92           0 :                 a = __darr_resize(a, nlen, esize);
      93           0 :                 dm = (struct darr_metadata *)a - 1;
      94             :         }
      95             : 
      96             : #define _a_at(i) ((char *)a + ((i)*esize))
      97           0 :         if (at < olen)
      98           0 :                 memmove(_a_at(at + count), _a_at(at), esize * (olen - at));
      99             : 
     100           0 :         dm->len = nlen;
     101             : 
     102           0 :         if (zero) {
     103           0 :                 if (at >= olen) {
     104           0 :                         at -= olen;
     105           0 :                         count += olen;
     106             :                 }
     107           0 :                 memset(_a_at(at), 0, esize * count);
     108             :         }
     109             : 
     110           0 :         return a;
     111             : #undef _a_at
     112             : }

Generated by: LCOV version v1.16-topotato