1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <osipparser2/internal.h>
21 
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_list.h>
24 
osip_list_init(osip_list_t * li)25 int osip_list_init(osip_list_t *li) {
26   if (li == NULL)
27     return OSIP_BADPARAMETER;
28 
29   memset(li, 0, sizeof(osip_list_t));
30   return OSIP_SUCCESS; /* ok */
31 }
32 
osip_list_clone(const osip_list_t * src,osip_list_t * dst,int (* clone_func)(void *,void **))33 int osip_list_clone(const osip_list_t *src, osip_list_t *dst, int (*clone_func)(void *, void **)) {
34   void *data;
35   void *data2;
36   int i;
37   osip_list_iterator_t iterator;
38 
39   for (data = osip_list_get_first((osip_list_t *) src, &iterator); osip_list_iterator_has_elem(iterator); data = osip_list_get_next(&iterator)) {
40     i = clone_func(data, &data2);
41 
42     if (i != 0)
43       return i;
44 
45     osip_list_add(dst, data2, -1);
46   }
47 
48   return OSIP_SUCCESS;
49 }
50 
osip_list_special_free(osip_list_t * li,void (* free_func)(void *))51 void osip_list_special_free(osip_list_t *li, void (*free_func)(void *)) {
52   void *element;
53 
54   if (li == NULL)
55     return;
56 
57   while (!osip_list_eol(li, 0)) {
58     element = (void *) osip_list_get(li, 0);
59     osip_list_remove(li, 0);
60 
61     if (free_func != NULL)
62       free_func(element);
63   }
64 }
65 
osip_list_ofchar_free(osip_list_t * li)66 void osip_list_ofchar_free(osip_list_t *li) {
67   char *chain;
68 
69   if (li == NULL)
70     return;
71 
72   while (!osip_list_eol(li, 0)) {
73     chain = (char *) osip_list_get(li, 0);
74     osip_list_remove(li, 0);
75     osip_free(chain);
76   }
77 }
78 
osip_list_size(const osip_list_t * li)79 int osip_list_size(const osip_list_t *li) {
80   if (li == NULL)
81     return OSIP_BADPARAMETER;
82 
83   return li->nb_elt;
84 }
85 
osip_list_eol(const osip_list_t * li,int i)86 int osip_list_eol(const osip_list_t *li, int i) {
87   if (li == NULL)
88     return OSIP_BADPARAMETER;
89 
90   if (i < li->nb_elt)
91     return OSIP_SUCCESS; /* not end of list */
92 
93   return 1; /* end of list */
94 }
95 
96 /* index starts from 0; */
osip_list_add(osip_list_t * li,void * el,int pos)97 int osip_list_add(osip_list_t *li, void *el, int pos) {
98   __node_t *ntmp;
99   int i = 0;
100 
101   if (li == NULL)
102     return OSIP_BADPARAMETER;
103 
104   if (li->nb_elt == 0) {
105     li->node = (__node_t *) osip_malloc(sizeof(__node_t));
106 
107     if (li->node == NULL)
108       return OSIP_NOMEM;
109 
110     li->node->element = el;
111     li->node->next = NULL;
112     li->nb_elt++;
113     return li->nb_elt;
114   }
115 
116   if (pos == -1 || pos >= li->nb_elt) { /* insert at the end  */
117     pos = li->nb_elt;
118   }
119 
120   ntmp = li->node; /* exist because nb_elt>0  */
121 
122   if (pos == 0) { /* pos = 0 insert before first elt  */
123     li->node = (__node_t *) osip_malloc(sizeof(__node_t));
124 
125     if (li->node == NULL) {
126       /* leave the list unchanged */
127       li->node = ntmp;
128       return OSIP_NOMEM;
129     }
130 
131     li->node->element = el;
132     li->node->next = ntmp;
133     li->nb_elt++;
134     return li->nb_elt;
135   }
136 
137   while (pos > i + 1) {
138     i++;
139     /* when pos>i next node exist  */
140     ntmp = ntmp->next;
141   }
142 
143   /* if pos==nb_elt next node does not exist  */
144   if (pos == li->nb_elt) {
145     ntmp->next = osip_malloc(sizeof(__node_t));
146 
147     if (ntmp->next == NULL)
148       return OSIP_NOMEM; /* leave the list unchanged */
149 
150     ntmp = ntmp->next;
151     ntmp->element = el;
152     ntmp->next = NULL;
153     li->nb_elt++;
154     return li->nb_elt;
155   }
156 
157   /* here pos==i so next node is where we want to insert new node */
158   {
159     __node_t *nextnode = ntmp->next;
160 
161     ntmp->next = osip_malloc(sizeof(__node_t));
162 
163     if (ntmp->next == NULL) {
164       /* leave the list unchanged */
165       ntmp->next = nextnode;
166       return OSIP_NOMEM;
167     }
168 
169     ntmp = ntmp->next;
170     ntmp->element = el;
171     ntmp->next = nextnode;
172     li->nb_elt++;
173   }
174   return li->nb_elt;
175 }
176 
177 /* index starts from 0 */
osip_list_get(const osip_list_t * li,int pos)178 void *osip_list_get(const osip_list_t *li, int pos) {
179   __node_t *ntmp;
180   int i = 0;
181 
182   if (li == NULL)
183     return NULL;
184 
185   if (pos < 0 || pos >= li->nb_elt)
186     /* element does not exist */
187     return NULL;
188 
189   ntmp = li->node; /* exist because nb_elt>0 */
190 
191   while (pos > i) {
192     i++;
193     ntmp = ntmp->next;
194   }
195 
196   return ntmp->element;
197 }
198 
199 /* added by bennewit@cs.tu-berlin.de */
osip_list_get_first(const osip_list_t * li,osip_list_iterator_t * iterator)200 void *osip_list_get_first(const osip_list_t *li, osip_list_iterator_t *iterator) {
201   if (li == NULL || 0 >= li->nb_elt) {
202     iterator->actual = 0;
203     return OSIP_SUCCESS;
204   }
205 
206   iterator->actual = li->node;
207   iterator->prev = (__node_t **) &li->node;
208   iterator->li = (osip_list_t *) li;
209   iterator->pos = 0;
210 
211   return li->node->element;
212 }
213 
214 /* added by bennewit@cs.tu-berlin.de */
osip_list_get_next(osip_list_iterator_t * iterator)215 void *osip_list_get_next(osip_list_iterator_t *iterator) {
216   if (iterator->actual == NULL) {
217     return OSIP_SUCCESS;
218   }
219 
220   iterator->prev = &(iterator->actual->next);
221   iterator->actual = iterator->actual->next;
222   ++(iterator->pos);
223 
224   if (osip_list_iterator_has_elem(*iterator)) {
225     return iterator->actual->element;
226   }
227 
228   iterator->actual = 0;
229   return OSIP_SUCCESS;
230 }
231 
232 /* added by bennewit@cs.tu-berlin.de */
osip_list_iterator_remove(osip_list_iterator_t * iterator)233 void *osip_list_iterator_remove(osip_list_iterator_t *iterator) {
234   if (osip_list_iterator_has_elem(*iterator)) {
235     --(iterator->li->nb_elt);
236 
237     *(iterator->prev) = iterator->actual->next;
238 
239     osip_free(iterator->actual);
240     iterator->actual = *(iterator->prev);
241   }
242 
243   if (osip_list_iterator_has_elem(*iterator)) {
244     return iterator->actual->element;
245   }
246 
247   return OSIP_SUCCESS;
248 }
249 
250 /* return -1 if failed */
osip_list_remove(osip_list_t * li,int pos)251 int osip_list_remove(osip_list_t *li, int pos) {
252   __node_t *ntmp;
253   int i = 0;
254 
255   if (li == NULL)
256     return OSIP_BADPARAMETER;
257 
258   if (pos < 0 || pos >= li->nb_elt)
259     /* element does not exist */
260     return OSIP_UNDEFINED_ERROR;
261 
262   ntmp = li->node; /* exist because nb_elt>0 */
263 
264   if (pos == 0) { /* special case  */
265     li->node = ntmp->next;
266     li->nb_elt--;
267     osip_free(ntmp);
268     return li->nb_elt;
269   }
270 
271   while (pos > i + 1) {
272     i++;
273     ntmp = ntmp->next;
274   }
275 
276   /* insert new node */
277   {
278     __node_t *remnode;
279 
280     remnode = ntmp->next;
281     ntmp->next = (ntmp->next)->next;
282     osip_free(remnode);
283     li->nb_elt--;
284   }
285   return li->nb_elt;
286 }
287