LCOV - code coverage report
Current view: top level - core - list.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 99.0 % 103 102
Test Date: 2025-03-25 15:17:39 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          324 : static int bf_list_node_new(bf_list_node **node, void *data)
      23              : {
      24              :     bf_list_node *_node;
      25              : 
      26          324 :     bf_assert(node);
      27              : 
      28          324 :     _node = calloc(1, sizeof(*_node));
      29          324 :     if (!_node)
      30              :         return -ENOMEM;
      31              : 
      32          324 :     _node->data = data;
      33          324 :     *node = _node;
      34              : 
      35          324 :     return 0;
      36              : }
      37              : 
      38              : /**
      39              :  * Free a list node.
      40              :  *
      41              :  * @param node Node to free. Can't be NULL.
      42              :  * @param free_data Callback to use to free the data. If NULL, the data is not
      43              :  *        freed.
      44              :  */
      45          324 : static void bf_list_node_free(bf_list_node **node,
      46              :                               void (*free_data)(void **data))
      47              : {
      48          324 :     bf_assert(node);
      49              : 
      50          324 :     if (free_data)
      51          315 :         free_data(&(*node)->data);
      52              :     freep((void *)node);
      53          324 : }
      54              : 
      55           12 : int bf_list_new(bf_list **list, const bf_list_ops *ops)
      56              : {
      57           11 :     _cleanup_bf_list_ bf_list *_list = NULL;
      58              : 
      59           12 :     bf_assert(list);
      60              : 
      61           11 :     _list = calloc(1, sizeof(*_list));
      62           11 :     if (!_list)
      63              :         return -ENOMEM;
      64              : 
      65           11 :     bf_list_init(_list, ops);
      66              : 
      67           11 :     *list = TAKE_PTR(_list);
      68              : 
      69           11 :     return 0;
      70              : }
      71              : 
      72           24 : void bf_list_free(bf_list **list)
      73              : {
      74           24 :     bf_assert(list);
      75              : 
      76           23 :     if (!*list)
      77              :         return;
      78              : 
      79           11 :     bf_list_clean(*list);
      80           11 :     free(*list);
      81           11 :     *list = NULL;
      82              : }
      83              : 
      84           77 : void bf_list_init(bf_list *list, const bf_list_ops *ops)
      85              : {
      86           77 :     bf_assert(list);
      87              : 
      88           76 :     list->len = 0;
      89           76 :     list->head = NULL;
      90           76 :     list->tail = NULL;
      91              : 
      92           76 :     if (ops)
      93           69 :         list->ops = *ops;
      94              :     else
      95            7 :         list->ops = bf_list_ops_default(NULL, NULL);
      96           76 : }
      97              : 
      98          143 : void bf_list_clean(bf_list *list)
      99              : {
     100          143 :     bf_assert(list);
     101              : 
     102          912 :     bf_list_foreach (list, node)
     103          314 :         bf_list_node_free(&node, list->ops.free);
     104              : 
     105          142 :     list->len = 0;
     106          142 :     list->head = NULL;
     107          142 :     list->tail = NULL;
     108          142 : }
     109              : 
     110            9 : int bf_list_marsh(const bf_list *list, struct bf_marsh **marsh)
     111              : {
     112            7 :     _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
     113              :     int r;
     114              : 
     115            9 :     bf_assert(list && marsh);
     116              : 
     117            7 :     r = bf_marsh_new(&_marsh, NULL, 0);
     118            7 :     if (r < 0)
     119              :         return r;
     120              : 
     121            7 :     if (list->ops.marsh) {
     122           56 :         bf_list_foreach (list, node) {
     123           22 :             _cleanup_bf_marsh_ struct bf_marsh *child = NULL;
     124              : 
     125           22 :             r = list->ops.marsh(bf_list_node_get_data(node), &child);
     126           22 :             if (r < 0)
     127              :                 return r;
     128              : 
     129           22 :             r = bf_marsh_add_child_obj(&_marsh, child);
     130           22 :             if (r < 0)
     131              :                 return r;
     132              :         }
     133              :     }
     134              : 
     135            7 :     *marsh = TAKE_PTR(_marsh);
     136              : 
     137            7 :     return 0;
     138              : }
     139              : 
     140           49 : int bf_list_add_head(bf_list *list, void *data)
     141              : {
     142           49 :     bf_list_node *node = NULL;
     143              :     int r;
     144              : 
     145           49 :     bf_assert(list);
     146              : 
     147           48 :     r = bf_list_node_new(&node, data);
     148           48 :     if (r < 0)
     149              :         return r;
     150              : 
     151           48 :     node->next = list->head;
     152           48 :     if (list->head)
     153           38 :         list->head->prev = node;
     154              : 
     155           48 :     list->head = node;
     156              : 
     157           48 :     if (!list->tail)
     158           10 :         list->tail = node;
     159              : 
     160           48 :     ++list->len;
     161              : 
     162           48 :     return 0;
     163              : }
     164              : 
     165          277 : int bf_list_add_tail(bf_list *list, void *data)
     166              : {
     167          277 :     bf_list_node *node = NULL;
     168              :     int r;
     169              : 
     170          277 :     bf_assert(list);
     171              : 
     172          276 :     r = bf_list_node_new(&node, data);
     173          276 :     if (r < 0)
     174              :         return r;
     175              : 
     176          276 :     node->prev = list->tail;
     177          276 :     if (list->tail)
     178          227 :         list->tail->next = node;
     179              : 
     180          276 :     list->tail = node;
     181              : 
     182          276 :     if (!list->head)
     183           49 :         list->head = node;
     184              : 
     185          276 :     ++list->len;
     186              : 
     187          276 :     return 0;
     188              : }
     189              : 
     190           10 : void bf_list_delete(bf_list *list, bf_list_node *node)
     191              : {
     192           10 :     bf_assert(list);
     193           10 :     bf_assert(node);
     194              : 
     195           10 :     if (list->head == node)
     196           10 :         list->head = node->next;
     197           10 :     if (list->tail == node)
     198            1 :         list->tail = node->prev;
     199              : 
     200           10 :     if (node->prev)
     201            0 :         node->prev->next = node->next;
     202           10 :     if (node->next)
     203            9 :         node->next->prev = node->prev;
     204              : 
     205           10 :     bf_list_node_free(&node, list->ops.free);
     206              : 
     207           10 :     --list->len;
     208           10 : }
     209              : 
     210            5 : void *bf_list_get_at(const bf_list *list, size_t index)
     211              : {
     212            5 :     bf_assert(list);
     213              : 
     214           53 :     bf_list_foreach (list, node) {
     215           26 :         if (index == 0)
     216            3 :             return node->data;
     217           23 :         --index;
     218              :     }
     219              : 
     220              :     return NULL;
     221              : }
        

Generated by: LCOV version 2.0-1