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: 2026-02-28 14:57:49 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                 :       15393 : static int bf_list_node_new(bf_list_node **node, void *data)
      22                 :             : {
      23                 :             :     bf_list_node *_node;
      24                 :             : 
      25                 :             :     assert(node);
      26                 :             : 
      27                 :       15393 :     _node = calloc(1, sizeof(*_node));
      28         [ +  - ]:       15393 :     if (!_node)
      29                 :             :         return -ENOMEM;
      30                 :             : 
      31                 :       15393 :     _node->data = data;
      32                 :       15393 :     *node = _node;
      33                 :             : 
      34                 :       15393 :     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                 :       15391 : static void bf_list_node_free(bf_list_node **node,
      45                 :             :                               void (*free_data)(void **data))
      46                 :             : {
      47                 :             :     assert(node);
      48                 :             : 
      49         [ +  + ]:       15391 :     if (free_data)
      50                 :       15360 :         free_data(&(*node)->data);
      51                 :             :     freep((void *)node);
      52                 :       15391 : }
      53                 :             : 
      54                 :        1259 : int bf_list_new(bf_list **list, const bf_list_ops *ops)
      55                 :             : {
      56                 :        1259 :     _free_bf_list_ bf_list *_list = NULL;
      57                 :             : 
      58                 :             :     assert(list);
      59                 :             : 
      60                 :        1259 :     _list = calloc(1, sizeof(*_list));
      61         [ +  - ]:        1259 :     if (!_list)
      62                 :             :         return -ENOMEM;
      63                 :             : 
      64                 :        1259 :     bf_list_init(_list, ops);
      65                 :             : 
      66                 :        1259 :     *list = TAKE_PTR(_list);
      67                 :             : 
      68                 :        1259 :     return 0;
      69                 :             : }
      70                 :             : 
      71                 :        3823 : void bf_list_free(bf_list **list)
      72                 :             : {
      73                 :             :     assert(list);
      74                 :             : 
      75         [ +  + ]:        3823 :     if (!*list)
      76                 :             :         return;
      77                 :             : 
      78                 :        1259 :     bf_list_clean(*list);
      79                 :        1259 :     free(*list);
      80                 :        1259 :     *list = NULL;
      81                 :             : }
      82                 :             : 
      83                 :        1668 : void bf_list_init(bf_list *list, const bf_list_ops *ops)
      84                 :             : {
      85                 :             :     assert(list);
      86                 :             : 
      87                 :        1668 :     list->len = 0;
      88                 :        1668 :     list->head = NULL;
      89                 :        1668 :     list->tail = NULL;
      90                 :             : 
      91         [ +  + ]:        1668 :     if (ops)
      92                 :        1666 :         list->ops = *ops;
      93                 :             :     else
      94                 :           2 :         list->ops = bf_list_ops_default(NULL, NULL);
      95                 :        1668 : }
      96                 :             : 
      97                 :       10503 : void bf_list_clean(bf_list *list)
      98                 :             : {
      99                 :             :     assert(list);
     100                 :             : 
     101   [ +  +  +  +  :       41664 :     bf_list_foreach (list, node)
                   +  + ]
     102                 :       10329 :         bf_list_node_free(&node, list->ops.free);
     103                 :             : 
     104                 :       10503 :     list->len = 0;
     105                 :       10503 :     list->head = NULL;
     106                 :       10503 :     list->tail = NULL;
     107                 :       10503 : }
     108                 :             : 
     109                 :        3100 : int bf_list_pack(const bf_list *list, bf_wpack_t *pack)
     110                 :             : {
     111                 :             :     assert(list);
     112                 :             :     assert(pack);
     113                 :             : 
     114         [ +  - ]:        3100 :     if (!list->ops.pack)
     115                 :             :         return -ENOTSUP;
     116                 :             : 
     117   [ +  +  +  +  :       32014 :     bf_list_foreach (list, node) {
                   +  + ]
     118         [ +  + ]:       12907 :         if (!bf_list_node_get_data(node)) {
     119                 :           8 :             bf_wpack_nil(pack);
     120                 :           8 :             continue;
     121                 :             :         }
     122                 :             : 
     123         [ +  + ]:       12899 :         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                 :       12894 :             bf_wpack_open_object(pack, NULL);
     128                 :       12894 :             list->ops.pack(bf_list_node_get_data(node), pack);
     129                 :       12894 :             bf_wpack_close_object(pack);
     130                 :             :         }
     131                 :             :     }
     132                 :             : 
     133         [ -  + ]:        3100 :     return bf_wpack_is_valid(pack) ? 0 : -EINVAL;
     134                 :             : }
     135                 :             : 
     136                 :         206 : int bf_list_push(bf_list *list, void **data)
     137                 :             : {
     138                 :             :     int r;
     139                 :             : 
     140                 :             :     assert(list);
     141                 :             :     assert(data);
     142                 :             : 
     143                 :         206 :     r = bf_list_add_tail(list, *data);
     144         [ +  - ]:         206 :     if (r < 0)
     145                 :             :         return r;
     146                 :             : 
     147                 :         206 :     TAKE_PTR(*data);
     148                 :             : 
     149                 :         206 :     return 0;
     150                 :             : }
     151                 :             : 
     152                 :          80 : int bf_list_add_head(bf_list *list, void *data)
     153                 :             : {
     154                 :          80 :     bf_list_node *node = NULL;
     155                 :             :     int r;
     156                 :             : 
     157                 :             :     assert(list);
     158                 :             : 
     159                 :          80 :     r = bf_list_node_new(&node, data);
     160         [ +  - ]:          80 :     if (r < 0)
     161                 :             :         return r;
     162                 :             : 
     163                 :          80 :     node->next = list->head;
     164         [ +  + ]:          80 :     if (list->head)
     165                 :          72 :         list->head->prev = node;
     166                 :             : 
     167                 :          80 :     list->head = node;
     168                 :             : 
     169         [ +  + ]:          80 :     if (!list->tail)
     170                 :           8 :         list->tail = node;
     171                 :             : 
     172                 :          80 :     ++list->len;
     173                 :             : 
     174                 :          80 :     return 0;
     175                 :             : }
     176                 :             : 
     177                 :       15313 : int bf_list_add_tail(bf_list *list, void *data)
     178                 :             : {
     179                 :       15313 :     bf_list_node *node = NULL;
     180                 :             :     int r;
     181                 :             : 
     182                 :             :     assert(list);
     183                 :             : 
     184                 :       15313 :     r = bf_list_node_new(&node, data);
     185         [ +  - ]:       15313 :     if (r < 0)
     186                 :             :         return r;
     187                 :             : 
     188                 :       15313 :     node->prev = list->tail;
     189         [ +  + ]:       15313 :     if (list->tail)
     190                 :       10596 :         list->tail->next = node;
     191                 :             : 
     192                 :       15313 :     list->tail = node;
     193                 :             : 
     194         [ +  + ]:       15313 :     if (!list->head)
     195                 :        4717 :         list->head = node;
     196                 :             : 
     197                 :       15313 :     ++list->len;
     198                 :             : 
     199                 :       15313 :     return 0;
     200                 :             : }
     201                 :             : 
     202                 :        5062 : void bf_list_delete(bf_list *list, bf_list_node *node)
     203                 :             : {
     204                 :             :     assert(list);
     205                 :             :     assert(node);
     206                 :             : 
     207         [ +  + ]:        5062 :     if (list->head == node)
     208                 :         568 :         list->head = node->next;
     209         [ +  + ]:        5062 :     if (list->tail == node)
     210                 :         189 :         list->tail = node->prev;
     211                 :             : 
     212         [ +  + ]:        5062 :     if (node->prev)
     213                 :        4494 :         node->prev->next = node->next;
     214         [ +  + ]:        5062 :     if (node->next)
     215                 :        4873 :         node->next->prev = node->prev;
     216                 :             : 
     217                 :        5062 :     bf_list_node_free(&node, list->ops.free);
     218                 :             : 
     219                 :        5062 :     --list->len;
     220                 :        5062 : }
     221                 :             : 
     222                 :         504 : void *bf_list_get_at(const bf_list *list, size_t index)
     223                 :             : {
     224                 :             :     assert(list);
     225                 :             : 
     226   [ +  -  +  + ]:        3595 :     bf_list_foreach (list, node) {
     227         [ +  + ]:        1797 :         if (index == 0)
     228                 :         503 :             return node->data;
     229         [ +  + ]:        1294 :         --index;
     230                 :             :     }
     231                 :             : 
     232                 :             :     return NULL;
     233                 :             : }
        

Generated by: LCOV version 2.0-1