LCOV - code coverage report
Current view: top level - core - list.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 99.1 % 106 105
Test Date: 2025-02-26 17:59:59 Functions: 100.0 % 11 11

            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 "list.h"
       7              : 
       8              : #include <errno.h>
       9              : #include <stdlib.h>
      10              : 
      11              : #include "core/helper.h"
      12              : #include "core/marsh.h"
      13              : 
      14              : /**
      15              :  * Create a new list node, with the given data.
      16              :  *
      17              :  * @param node New node pointer. Must be non-NULL.. If the function fails, this
      18              :  *            parameter remains unchanged.
      19              :  * @param data Data to store in the new node. Can be NULL.
      20              :  * @return 0 on success or negative errno code on failure.
      21              :  */
      22          311 : static int bf_list_node_new(bf_list_node **node, void *data)
      23              : {
      24              :     bf_list_node *_node;
      25              : 
      26          311 :     bf_assert(node);
      27              : 
      28          311 :     _node = calloc(1, sizeof(*_node));
      29          311 :     if (!_node)
      30              :         return -ENOMEM;
      31              : 
      32          311 :     _node->data = data;
      33          311 :     *node = _node;
      34              : 
      35          311 :     return 0;
      36              : }
      37              : 
      38              : /**
      39              :  * Free a list node. Must be non-NULL.
      40              :  *
      41              :  * The data contained in the node will also be freed using the function provided
      42              :  * in the list's ops.
      43              :  *
      44              :  * @param node Node to free.
      45              :  * @param free_data Pointer to a function use to free the node's data.
      46              :  */
      47          311 : static void bf_list_node_free(bf_list_node **node,
      48              :                               void (*free_data)(void **data))
      49              : {
      50          311 :     bf_assert(node);
      51              : 
      52          311 :     free_data(&(*node)->data);
      53          311 :     free(*node);
      54          311 :     *node = NULL;
      55          311 : }
      56              : 
      57           12 : int bf_list_new(bf_list **list, const bf_list_ops *ops)
      58              : {
      59           10 :     _cleanup_bf_list_ bf_list *_list = NULL;
      60              : 
      61           12 :     bf_assert(list);
      62           11 :     bf_assert(ops);
      63           10 :     bf_assert(ops->free);
      64              : 
      65           10 :     _list = calloc(1, sizeof(*_list));
      66           10 :     if (!_list)
      67              :         return -ENOMEM;
      68              : 
      69           10 :     bf_list_init(_list, ops);
      70              : 
      71           10 :     *list = TAKE_PTR(_list);
      72              : 
      73           10 :     return 0;
      74              : }
      75              : 
      76           22 : void bf_list_free(bf_list **list)
      77              : {
      78           22 :     bf_assert(list);
      79              : 
      80           21 :     if (!*list)
      81              :         return;
      82              : 
      83           10 :     bf_list_clean(*list);
      84           10 :     free(*list);
      85           10 :     *list = NULL;
      86              : }
      87              : 
      88           76 : void bf_list_init(bf_list *list, const bf_list_ops *ops)
      89              : {
      90           76 :     bf_assert(list);
      91           75 :     bf_assert(ops);
      92           74 :     bf_assert(ops->free);
      93              : 
      94           74 :     list->len = 0;
      95           74 :     list->head = NULL;
      96           74 :     list->tail = NULL;
      97           74 :     list->ops = *ops;
      98           74 : }
      99              : 
     100          141 : void bf_list_clean(bf_list *list)
     101              : {
     102          141 :     bf_assert(list);
     103              : 
     104          882 :     bf_list_foreach (list, node)
     105          301 :         bf_list_node_free(&node, list->ops.free);
     106              : 
     107          140 :     list->len = 0;
     108          140 :     list->head = NULL;
     109          140 :     list->tail = NULL;
     110          140 : }
     111              : 
     112            9 : int bf_list_marsh(const bf_list *list, struct bf_marsh **marsh)
     113              : {
     114            6 :     _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
     115              :     int r;
     116              : 
     117            9 :     bf_assert(list && marsh);
     118            7 :     bf_assert(list->ops.marsh);
     119              : 
     120            6 :     r = bf_marsh_new(&_marsh, NULL, 0);
     121            6 :     if (r < 0)
     122              :         return r;
     123              : 
     124           56 :     bf_list_foreach (list, node) {
     125           22 :         _cleanup_bf_marsh_ struct bf_marsh *child = NULL;
     126              : 
     127           22 :         r = list->ops.marsh(bf_list_node_get_data(node), &child);
     128           22 :         if (r < 0)
     129              :             return r;
     130              : 
     131           22 :         r = bf_marsh_add_child_obj(&_marsh, child);
     132           22 :         if (r < 0)
     133              :             return r;
     134              :     }
     135              : 
     136            6 :     *marsh = TAKE_PTR(_marsh);
     137              : 
     138            6 :     return 0;
     139              : }
     140              : 
     141           46 : int bf_list_add_head(bf_list *list, void *data)
     142              : {
     143           46 :     bf_list_node *node = NULL;
     144              :     int r;
     145              : 
     146           46 :     bf_assert(list);
     147              : 
     148           45 :     r = bf_list_node_new(&node, data);
     149           45 :     if (r < 0)
     150              :         return r;
     151              : 
     152           45 :     node->next = list->head;
     153           45 :     if (list->head)
     154           36 :         list->head->prev = node;
     155              : 
     156           45 :     list->head = node;
     157              : 
     158           45 :     if (!list->tail)
     159            9 :         list->tail = node;
     160              : 
     161           45 :     ++list->len;
     162              : 
     163           45 :     return 0;
     164              : }
     165              : 
     166          267 : int bf_list_add_tail(bf_list *list, void *data)
     167              : {
     168          267 :     bf_list_node *node = NULL;
     169              :     int r;
     170              : 
     171          267 :     bf_assert(list);
     172              : 
     173          266 :     r = bf_list_node_new(&node, data);
     174          266 :     if (r < 0)
     175              :         return r;
     176              : 
     177          266 :     node->prev = list->tail;
     178          266 :     if (list->tail)
     179          218 :         list->tail->next = node;
     180              : 
     181          266 :     list->tail = node;
     182              : 
     183          266 :     if (!list->head)
     184           48 :         list->head = node;
     185              : 
     186          266 :     ++list->len;
     187              : 
     188          266 :     return 0;
     189              : }
     190              : 
     191           10 : void bf_list_delete(bf_list *list, bf_list_node *node)
     192              : {
     193           10 :     bf_assert(list);
     194           10 :     bf_assert(node);
     195              : 
     196           10 :     if (list->head == node)
     197           10 :         list->head = node->next;
     198           10 :     if (list->tail == node)
     199            1 :         list->tail = node->prev;
     200              : 
     201           10 :     if (node->prev)
     202            0 :         node->prev->next = node->next;
     203           10 :     if (node->next)
     204            9 :         node->next->prev = node->prev;
     205              : 
     206           10 :     bf_list_node_free(&node, list->ops.free);
     207              : 
     208           10 :     --list->len;
     209           10 : }
     210              : 
     211            5 : void *bf_list_get_at(const bf_list *list, size_t index)
     212              : {
     213            5 :     bf_assert(list);
     214              : 
     215           53 :     bf_list_foreach (list, node) {
     216           26 :         if (index == 0)
     217            3 :             return node->data;
     218           23 :         --index;
     219              :     }
     220              : 
     221              :     return NULL;
     222              : }
        

Generated by: LCOV version 2.0-1