source: trunk/libtransmission/list.c

Last change on this file was 14319, checked in by jordan, 6 years ago

(trunk, libT) #5735 'segfault iside node_alloc' -- fixed with patch by benjarobin

  • Property svn:keywords set to Date Rev Author Id
File size: 4.0 KB
Line 
1/*
2 * This file Copyright (C) 2007-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: list.c 14319 2014-07-06 20:06:45Z mikedld $
8 */
9
10#include "transmission.h"
11#include "list.h"
12#include "platform.h"
13#include "utils.h"
14
15static const tr_list TR_LIST_CLEAR = { NULL, NULL, NULL };
16
17static tr_list * recycled_nodes = NULL;
18
19static tr_lock*
20getRecycledNodesLock (void)
21{
22  static tr_lock * l = NULL;
23
24  if (!l)
25    l = tr_lockNew ();
26
27  return l;
28}
29
30static tr_list*
31node_alloc (void)
32{
33  tr_list * ret = NULL;
34  tr_lock * lock = getRecycledNodesLock ();
35
36  tr_lockLock (lock);
37
38  if (recycled_nodes != NULL)
39    {
40      ret = recycled_nodes;
41      recycled_nodes = recycled_nodes->next;
42    }
43
44  tr_lockUnlock (lock);
45
46  if (ret == NULL)
47    {
48      ret = tr_new (tr_list, 1);
49    }
50
51  *ret = TR_LIST_CLEAR;
52  return ret;
53}
54
55static void
56node_free (tr_list* node)
57{
58  tr_lock * lock = getRecycledNodesLock ();
59
60  if (node != NULL)
61    {
62      *node = TR_LIST_CLEAR;
63      tr_lockLock (lock);
64      node->next = recycled_nodes;
65      recycled_nodes = node;
66      tr_lockUnlock (lock);
67    }
68}
69
70/***
71****
72***/
73
74void
75tr_list_free (tr_list**         list,
76              TrListForeachFunc data_free_func)
77{
78  while (*list)
79    {
80      tr_list *node = *list;
81      *list = (*list)->next;
82      if (data_free_func)
83        data_free_func (node->data);
84      node_free (node);
85    }
86}
87
88void
89tr_list_prepend (tr_list ** list,
90                 void *     data)
91{
92  tr_list * node = node_alloc ();
93
94  node->data = data;
95  node->next = *list;
96  if (*list)
97    (*list)->prev = node;
98  *list = node;
99}
100
101void
102tr_list_append (tr_list ** list,
103                void *     data)
104{
105  tr_list * node = node_alloc ();
106
107  node->data = data;
108
109  if (!*list)
110    {
111      *list = node;
112    }
113  else
114    {
115      tr_list * l = *list;
116
117      while (l->next)
118        l = l->next;
119
120      l->next = node;
121      node->prev = l;
122    }
123}
124
125static tr_list*
126tr_list_find_data (tr_list *    list,
127                   const void * data)
128{
129  for (; list; list = list->next)
130    if (list->data == data)
131      return list;
132
133  return NULL;
134}
135
136static void*
137tr_list_remove_node (tr_list ** list,
138                     tr_list *  node)
139{
140  void *    data;
141  tr_list * prev = node ? node->prev : NULL;
142  tr_list * next = node ? node->next : NULL;
143
144  if (prev) prev->next = next;
145  if (next) next->prev = prev;
146  if (*list == node) *list = next;
147  data = node ? node->data : NULL;
148  node_free (node);
149  return data;
150}
151
152void*
153tr_list_pop_front (tr_list ** list)
154{
155  void * ret = NULL;
156
157  if (*list)
158    {
159      ret = (*list)->data;
160      tr_list_remove_node (list, *list);
161    }
162
163  return ret;
164}
165
166void*
167tr_list_remove_data (tr_list **   list,
168                     const void * data)
169{
170  return tr_list_remove_node (list, tr_list_find_data (*list, data));
171}
172
173void*
174tr_list_remove (tr_list **        list,
175                const void *      b,
176                TrListCompareFunc compare_func)
177{
178  return tr_list_remove_node (list, tr_list_find (*list, b, compare_func));
179}
180
181tr_list*
182tr_list_find (tr_list *         list,
183              const void *      b,
184              TrListCompareFunc func)
185{
186  for (; list; list = list->next)
187    if (!func (list->data, b))
188      return list;
189
190  return NULL;
191}
192
193void
194tr_list_insert_sorted (tr_list            ** list,
195                       void                * data,
196                       TrListCompareFunc     compare)
197{
198  /* find l, the node that we'll insert this data before */
199  tr_list * l;
200
201  for (l = *list; l != NULL; l = l->next)
202    {
203      const int c = (compare)(data, l->data);
204      if (c <= 0)
205        break;
206    }
207
208  if (l == NULL)
209    {
210      tr_list_append (list, data);
211    }
212  else if (l == *list)
213    {
214      tr_list_prepend (list, data);
215    }
216  else
217    {
218      tr_list * node = node_alloc ();
219      node->data = data;
220      node->prev = l->prev;
221      node->next = l;
222      node->prev->next = node;
223      node->next->prev = node;
224    }
225}
226
227int
228tr_list_size (const tr_list * list)
229{
230  int size = 0;
231
232  while (list)
233    {
234      ++size;
235      list = list->next;
236    }
237
238  return size;
239}
Note: See TracBrowser for help on using the repository browser.