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