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