LCOV - code coverage report
Current view: top level - libbpfilter - list.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 100.0 % 95 95
Test Date: 2025-11-24 12:34:34 Functions: 100.0 % 12 12
Branches: 86.7 % 60 52

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-2.0-only
       2                 :             : /*
       3                 :             :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "bpfilter/list.h"
       7                 :             : 
       8                 :             : #include <errno.h>
       9                 :             : #include <stdlib.h>
      10                 :             : 
      11                 :             : #include "bpfilter/helper.h"
      12                 :             : 
      13                 :             : /**
      14                 :             :  * Create a new list node, with the given data.
      15                 :             :  *
      16                 :             :  * @param node New node pointer. Must be non-NULL.. If the function fails, this
      17                 :             :  *            parameter remains unchanged.
      18                 :             :  * @param data Data to store in the new node. Can be NULL.
      19                 :             :  * @return 0 on success or negative errno code on failure.
      20                 :             :  */
      21                 :       13411 : static int bf_list_node_new(bf_list_node **node, void *data)
      22                 :             : {
      23                 :             :     bf_list_node *_node;
      24                 :             : 
      25                 :             :     bf_assert(node);
      26                 :             : 
      27                 :       13411 :     _node = calloc(1, sizeof(*_node));
      28         [ +  - ]:       13411 :     if (!_node)
      29                 :             :         return -ENOMEM;
      30                 :             : 
      31                 :       13411 :     _node->data = data;
      32                 :       13411 :     *node = _node;
      33                 :             : 
      34                 :       13411 :     return 0;
      35                 :             : }
      36                 :             : 
      37                 :             : /**
      38                 :             :  * Free a list node.
      39                 :             :  *
      40                 :             :  * @param node Node to free. Can't be NULL.
      41                 :             :  * @param free_data Callback to use to free the data. If NULL, the data is not
      42                 :             :  *        freed.
      43                 :             :  */
      44                 :       13409 : static void bf_list_node_free(bf_list_node **node,
      45                 :             :                               void (*free_data)(void **data))
      46                 :             : {
      47                 :             :     bf_assert(node);
      48                 :             : 
      49         [ +  + ]:       13409 :     if (free_data)
      50                 :       13394 :         free_data(&(*node)->data);
      51                 :             :     freep((void *)node);
      52                 :       13409 : }
      53                 :             : 
      54                 :        1111 : int bf_list_new(bf_list **list, const bf_list_ops *ops)
      55                 :             : {
      56                 :        1111 :     _free_bf_list_ bf_list *_list = NULL;
      57                 :             : 
      58                 :             :     bf_assert(list);
      59                 :             : 
      60                 :        1111 :     _list = calloc(1, sizeof(*_list));
      61         [ +  - ]:        1111 :     if (!_list)
      62                 :             :         return -ENOMEM;
      63                 :             : 
      64                 :        1111 :     bf_list_init(_list, ops);
      65                 :             : 
      66                 :        1111 :     *list = TAKE_PTR(_list);
      67                 :             : 
      68                 :        1111 :     return 0;
      69                 :             : }
      70                 :             : 
      71                 :        3423 : void bf_list_free(bf_list **list)
      72                 :             : {
      73                 :             :     bf_assert(list);
      74                 :             : 
      75         [ +  + ]:        3423 :     if (!*list)
      76                 :             :         return;
      77                 :             : 
      78                 :        1111 :     bf_list_clean(*list);
      79                 :        1111 :     free(*list);
      80                 :        1111 :     *list = NULL;
      81                 :             : }
      82                 :             : 
      83                 :        1498 : void bf_list_init(bf_list *list, const bf_list_ops *ops)
      84                 :             : {
      85                 :             :     bf_assert(list);
      86                 :             : 
      87                 :        1498 :     list->len = 0;
      88                 :        1498 :     list->head = NULL;
      89                 :        1498 :     list->tail = NULL;
      90                 :             : 
      91         [ +  + ]:        1498 :     if (ops)
      92                 :        1496 :         list->ops = *ops;
      93                 :             :     else
      94                 :           2 :         list->ops = bf_list_ops_default(NULL, NULL);
      95                 :        1498 : }
      96                 :             : 
      97                 :        6701 : void bf_list_clean(bf_list *list)
      98                 :             : {
      99                 :             :     bf_assert(list);
     100                 :             : 
     101   [ +  +  +  +  :       31356 :     bf_list_foreach (list, node)
                   +  + ]
     102                 :        8977 :         bf_list_node_free(&node, list->ops.free);
     103                 :             : 
     104                 :        6701 :     list->len = 0;
     105                 :        6701 :     list->head = NULL;
     106                 :        6701 :     list->tail = NULL;
     107                 :        6701 : }
     108                 :             : 
     109                 :        2804 : int bf_list_pack(const bf_list *list, bf_wpack_t *pack)
     110                 :             : {
     111                 :             :     bf_assert(list);
     112                 :             :     bf_assert(pack);
     113                 :             : 
     114         [ +  - ]:        2804 :     if (!list->ops.pack)
     115                 :             :         return -ENOTSUP;
     116                 :             : 
     117   [ +  +  +  +  :       30882 :     bf_list_foreach (list, node) {
                   +  + ]
     118         [ +  + ]:       12637 :         if (!bf_list_node_get_data(node)) {
     119                 :           1 :             bf_wpack_nil(pack);
     120                 :           1 :             continue;
     121                 :             :         }
     122                 :             : 
     123         [ +  + ]:       12636 :         if (list->ops.pack == (bf_list_ops_pack)bf_list_pack) {
     124                 :             :             // Handle nested lists
     125                 :           5 :             bf_wpack_list(pack, bf_list_node_get_data(node));
     126                 :             :         } else {
     127                 :       12631 :             bf_wpack_open_object(pack, NULL);
     128                 :       12631 :             list->ops.pack(bf_list_node_get_data(node), pack);
     129                 :       12631 :             bf_wpack_close_object(pack);
     130                 :             :         }
     131                 :             :     }
     132                 :             : 
     133         [ -  + ]:        2804 :     return bf_wpack_is_valid(pack) ? 0 : -EINVAL;
     134                 :             : }
     135                 :             : 
     136                 :          85 : int bf_list_push(bf_list *list, void **data)
     137                 :             : {
     138                 :             :     int r;
     139                 :             : 
     140                 :             :     bf_assert(data);
     141                 :             : 
     142                 :          85 :     r = bf_list_add_tail(list, *data);
     143         [ +  - ]:          85 :     if (r < 0)
     144                 :             :         return r;
     145                 :             : 
     146                 :          85 :     TAKE_PTR(*data);
     147                 :             : 
     148                 :          85 :     return 0;
     149                 :             : }
     150                 :             : 
     151                 :          80 : int bf_list_add_head(bf_list *list, void *data)
     152                 :             : {
     153                 :          80 :     bf_list_node *node = NULL;
     154                 :             :     int r;
     155                 :             : 
     156                 :             :     bf_assert(list);
     157                 :             : 
     158                 :          80 :     r = bf_list_node_new(&node, data);
     159         [ +  - ]:          80 :     if (r < 0)
     160                 :             :         return r;
     161                 :             : 
     162                 :          80 :     node->next = list->head;
     163         [ +  + ]:          80 :     if (list->head)
     164                 :          72 :         list->head->prev = node;
     165                 :             : 
     166                 :          80 :     list->head = node;
     167                 :             : 
     168         [ +  + ]:          80 :     if (!list->tail)
     169                 :           8 :         list->tail = node;
     170                 :             : 
     171                 :          80 :     ++list->len;
     172                 :             : 
     173                 :          80 :     return 0;
     174                 :             : }
     175                 :             : 
     176                 :       13331 : int bf_list_add_tail(bf_list *list, void *data)
     177                 :             : {
     178                 :       13331 :     bf_list_node *node = NULL;
     179                 :             :     int r;
     180                 :             : 
     181                 :             :     bf_assert(list);
     182                 :             : 
     183                 :       13331 :     r = bf_list_node_new(&node, data);
     184         [ +  - ]:       13331 :     if (r < 0)
     185                 :             :         return r;
     186                 :             : 
     187                 :       13331 :     node->prev = list->tail;
     188         [ +  + ]:       13331 :     if (list->tail)
     189                 :        9565 :         list->tail->next = node;
     190                 :             : 
     191                 :       13331 :     list->tail = node;
     192                 :             : 
     193         [ +  + ]:       13331 :     if (!list->head)
     194                 :        3766 :         list->head = node;
     195                 :             : 
     196                 :       13331 :     ++list->len;
     197                 :             : 
     198                 :       13331 :     return 0;
     199                 :             : }
     200                 :             : 
     201                 :        4432 : void bf_list_delete(bf_list *list, bf_list_node *node)
     202                 :             : {
     203                 :             :     bf_assert(list);
     204                 :             :     bf_assert(node);
     205                 :             : 
     206         [ +  + ]:        4432 :     if (list->head == node)
     207                 :         293 :         list->head = node->next;
     208         [ +  + ]:        4432 :     if (list->tail == node)
     209                 :         119 :         list->tail = node->prev;
     210                 :             : 
     211         [ +  + ]:        4432 :     if (node->prev)
     212                 :        4139 :         node->prev->next = node->next;
     213         [ +  + ]:        4432 :     if (node->next)
     214                 :        4313 :         node->next->prev = node->prev;
     215                 :             : 
     216                 :        4432 :     bf_list_node_free(&node, list->ops.free);
     217                 :             : 
     218                 :        4432 :     --list->len;
     219                 :        4432 : }
     220                 :             : 
     221                 :         184 : void *bf_list_get_at(const bf_list *list, size_t index)
     222                 :             : {
     223                 :             :     bf_assert(list);
     224                 :             : 
     225   [ +  -  +  + ]:        1773 :     bf_list_foreach (list, node) {
     226         [ +  + ]:         886 :         if (index == 0)
     227                 :         183 :             return node->data;
     228         [ +  + ]:         703 :         --index;
     229                 :             :     }
     230                 :             : 
     231                 :             :     return NULL;
     232                 :             : }
        

Generated by: LCOV version 2.0-1