Imported Upstream version 2.7
[ossec-hids.git] / src / shared / list_op.c
1 /* @(#) $Id: ./src/shared/list_op.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All right reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  */
12
13 /* Common API for dealing with lists */
14
15
16 #include "shared.h"
17
18
19 /* Create the list
20  * Return NULL on error
21  */
22 OSList *OSList_Create()
23 {
24     OSList *my_list;
25
26     my_list = calloc(1, sizeof(OSList));
27     if(!my_list)
28         return(NULL);
29
30     my_list->first_node = NULL;
31     my_list->last_node = NULL;
32     my_list->cur_node = NULL;
33     my_list->currently_size = 0;
34     my_list->max_size = 0;
35     my_list->free_data_function = NULL;
36
37     return(my_list);
38 }
39
40
41 /* Set the maximum number of elements
42  * in the list. Returns 0 on error or
43  * 1 on success.
44  */
45 int OSList_SetMaxSize(OSList *list, int max_size)
46 {
47     if(!list)
48     {
49         return(0);
50     }
51
52     /* Minimum size is 1 */
53     if(max_size <= 1)
54     {
55         return(0);
56     }
57
58     list->max_size = max_size;
59
60     return(1);
61 }
62
63
64 /* Set the pointer to the function to free the memory
65  * data.
66  */
67 int OSList_SetFreeDataPointer(OSList *list, void *free_data_function)
68 {
69     if(!list)
70     {
71         return(0);
72     }
73
74     list->free_data_function = free_data_function;
75     return(1);
76 }
77
78
79 /* Get first node from list
80  * Returns null on invalid list
81  */
82 OSListNode *OSList_GetFirstNode(OSList *list)
83 {
84     list->cur_node = list->first_node;
85     return(list->first_node);
86 }
87
88
89 /* Get last node from list
90  * Returns null on invalid list
91  */
92 OSListNode *OSList_GetLastNode(OSList *list)
93 {
94     list->cur_node = list->last_node;
95     return(list->last_node);
96 }
97
98
99 /* Get next node from list
100  * Returns null on invalid list or at
101  * the end of the list
102  */
103 OSListNode *OSList_GetNextNode(OSList *list)
104 {
105     if(list->cur_node == NULL)
106         return(NULL);
107
108     list->cur_node = list->cur_node->next;
109
110     return(list->cur_node);
111 }
112
113
114 /* Get the prev node from the list
115  * Returns NULL at the beginning
116  */
117 OSListNode *OSList_GetPrevNode(OSList *list)
118 {
119     if(list->cur_node == NULL)
120         return(NULL);
121
122     list->cur_node = list->cur_node->prev;
123
124     return(list->cur_node);
125 }
126
127
128 /* Get the currently node.
129  * Returns null when no currently node is available
130  */
131 OSListNode *OSList_GetCurrentlyNode(OSList *list)
132 {
133     return(list->cur_node);
134 }
135
136
137 /* Delete first node from list */
138 void OSList_DeleteOldestNode(OSList *list)
139 {
140     OSListNode *next;
141
142     if(list->first_node)
143     {
144         next = list->first_node->next;
145         if(next)
146             next->prev = NULL;
147         else
148             list->last_node = next;
149
150         free(list->first_node);
151         list->first_node = next;
152     }
153     else
154     {
155         merror("%s: No Oldest node to delete", __local_name);
156     }
157
158     return;
159 }
160
161
162 /* Delete this node from list
163  * Pointer goes to the next node available.
164  */
165 void OSList_DeleteThisNode(OSList *list, OSListNode *thisnode)
166 {
167     OSListNode *prev;
168     OSListNode *next;
169
170     if(thisnode == NULL)
171         return;
172
173     prev = thisnode->prev;
174     next = thisnode->next;
175
176     /* Setting the previous node of the next one
177      * and the next node of the previous one.. :)
178      */
179     if(prev && next)
180     {
181         prev->next = next;
182         next->prev = prev;
183     }
184     else if(prev)
185     {
186         prev->next = NULL;
187         list->last_node = prev;
188     }
189     else if(next)
190     {
191         next->prev = NULL;
192         list->first_node = next;
193     }
194     else
195     {
196         list->last_node = NULL;
197         list->first_node = NULL;
198     }
199
200
201     /* Freeing the node memory */
202     free(thisnode);
203
204     /* Setting the currently node to the next one */
205     list->cur_node = next;
206
207     list->currently_size--;
208 }
209
210
211 /* Delete currently node from list
212  * Pointer goes to the next node available.
213  * Returns void
214  */
215 void OSList_DeleteCurrentlyNode(OSList *list)
216 {
217     OSListNode *prev;
218     OSListNode *next;
219
220     if(list->cur_node == NULL)
221         return;
222
223     prev = list->cur_node->prev;
224     next = list->cur_node->next;
225
226
227     /* Setting the previous node of the next one
228      * and the next node of the previous one.. :)
229      */
230     if(prev && next)
231     {
232         prev->next = next;
233         next->prev = prev;
234     }
235     else if(prev)
236     {
237         prev->next = NULL;
238         list->last_node = prev;
239     }
240     else if(next)
241     {
242         next->prev = NULL;
243         list->first_node = next;
244     }
245     else
246     {
247         list->last_node = NULL;
248         list->first_node = NULL;
249     }
250
251     /* Freeing the node memory */
252     free(list->cur_node);
253
254     /* Setting the currently node to the next one */
255     list->cur_node = next;
256
257     list->currently_size--;
258 }
259
260
261 /* Add data to the list
262  * Returns 1 on success and 0 on failure
263  */
264 int OSList_AddData(OSList *list, void *data)
265 {
266     OSListNode *newnode;
267
268
269     /* Allocating memory for new node */
270     newnode = calloc(1, sizeof(OSListNode));
271     if(!newnode)
272     {
273         merror(MEM_ERROR, __local_name);
274         return(0);
275     }
276
277     newnode->prev = list->last_node;
278     newnode->next = NULL;
279     newnode->data = data;
280
281
282     /* If we don't havea first node, assign it */
283     if(!list->first_node)
284     {
285         list->first_node = newnode;
286     }
287
288     /* If we have a last node, set the next to new node */
289     if(list->last_node)
290     {
291         list->last_node->next = newnode;
292     }
293
294
295     /* newnode become last node */
296     list->last_node = newnode;
297
298     /* Increment list size */
299     list->currently_size++;
300
301     /* if currently_size higher than the maximum size, remove the
302      * oldest node (first one)
303      */
304     if(list->max_size)
305     {
306         if(list->currently_size > list->max_size)
307         {
308             /* Remove first node */
309             newnode = list->first_node->next;
310
311             newnode->prev = NULL;
312
313             /* Clearing any internal memory using the pointer */
314             if(list->free_data_function)
315             {
316                 list->free_data_function(list->first_node->data);
317             }
318
319             /* Clearing the memory */
320             free(list->first_node);
321
322             /* First node become the ex first->next */
323             list->first_node = newnode;
324
325             /* Reduce list size */
326             list->currently_size--;
327         }
328     }
329
330     return(1);
331 }
332
333 /* EOF */