summaryrefslogtreecommitdiff
path: root/src/slist.c
blob: 249a3cfea35506743458eb12ddd17cf7fe5894a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 *  gstdvbbackend
 *
 *  gstdvbbackend is a small programm which captures a given set of dvb
 *  channels from one dvb device and provides the streams via minimal http.
 *
 *
 *  Copyright (C) 2011-2016 Christian Pointner <equinox@spreadspace.org>
 *
 *  This file is part of gstdvbbackend.
 *
 *  gstdvbbackend is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *
 *  gstdvbbackend is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with gstdvbbackend. If not, see <http://www.gnu.org/licenses/>.
 */

#include <unistd.h>
#include <stdlib.h>

#include "datatypes.h"

#include "slist.h"

slist_element_t* slist_get_last(slist_element_t* first)
{
  if(!first)
    return NULL;

  while(first->next_)
    first = first->next_;

  return first;
}

int slist_init(slist_t* lst, void (*delete_element)(void*))
{
  if(!lst || !delete_element)
    return -1;

  lst->delete_element = delete_element;
  lst->first_ = NULL;

  return 0;
}

slist_element_t* slist_add(slist_t* lst, void* data)
{
  if(!lst || !data)
    return NULL;

  slist_element_t* new_element = malloc(sizeof(slist_element_t));
  if(!new_element)
    return NULL;

  new_element->data_ = data;
  new_element->next_ = NULL;

  if(!lst->first_)
    lst->first_ = new_element;
  else
    slist_get_last(lst->first_)->next_ = new_element;

  return new_element;
}

void slist_remove(slist_t* lst, void* data)
{
  if(!lst || !lst->first_ || !data)
    return;

  slist_element_t* tmp = lst->first_->next_;
  slist_element_t* prev = lst->first_;
  if(lst->first_->data_ == data) {
    lst->first_ = tmp;
    lst->delete_element(prev->data_);
    free(prev);
  }
  else {
    while(tmp) {
      if(tmp->data_ == data) {
        prev->next_ = tmp->next_;
        lst->delete_element(tmp->data_);
        free(tmp);
        return;
      }
      prev = tmp;
      tmp = tmp->next_;
    }
  }
}

void slist_clear(slist_t* lst)
{
  if(!lst || !lst->first_)
    return;

  do {
    slist_element_t* deletee = lst->first_;
    lst->first_ = lst->first_->next_;
    lst->delete_element(deletee->data_);
    free(deletee);
  }
  while(lst->first_);

  lst->first_ = NULL;
}

int slist_length(slist_t* lst)
{
  if(!lst || !lst->first_)
    return 0;

  int len = 0;
  slist_element_t* tmp;
  for(tmp = lst->first_; tmp; tmp = tmp->next_)
    len++;

  return len;
}