1 /*
2   Copyright (c) <2007-2012> <Barbara Philippot - Olivier Courtin>
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy
5   of this software and associated documentation files (the "Software"), to deal
6   in the Software without restriction, including without limitation the rights
7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8   copies of the Software, and to permit persons to whom the Software is
9   furnished to do so, subject to the following conditions:
10 
11   The above copyright notice and this permission notice shall be included in
12   all copies or substantial portions of the Software.
13 
14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20   IN THE SOFTWARE.
21 */
22 
23 
24 #include <stdlib.h>
25 #include <stdio.h>              /* FILE */
26 #include <string.h>             /* strncmp */
27 #include <limits.h>
28 #include <assert.h>
29 
30 #include "../ows/ows.h"
31 
32 
33 /*
34  * Initialize a multiple list structure
35  */
mlist_init()36 mlist *mlist_init()
37 {
38   mlist *ml = NULL;
39 
40   ml = malloc(sizeof(mlist));
41   assert(ml);
42 
43   ml->first = NULL;
44   ml->last = NULL;
45   ml->size = 0;
46 
47   return ml;
48 }
49 
50 
51 /*
52  * Free a multiple list structure
53  */
mlist_free(mlist * ml)54 void mlist_free(mlist * ml)
55 {
56   assert(ml);
57 
58   while (ml->first) mlist_node_free(ml, ml->first);
59 
60   ml->last = NULL;
61   free(ml);
62   ml = NULL;
63 }
64 
65 
66 /*
67  * Add a given list to the end of a mlist
68  * Careful list is passed by reference,
69  * and must be free with mlist_free()
70  */
mlist_add(mlist * ml,list * value)71 void mlist_add(mlist * ml, list * value)
72 {
73   mlist_node *mln;
74 
75   assert(ml);
76   assert(value);
77   assert(ml->size < UINT_MAX);
78 
79   mln = mlist_node_init();
80 
81   mln->value = value;
82 
83   if (!ml->first) {
84     mln->prev = NULL;
85     ml->first = mln;
86   } else {
87     mln->prev = ml->last;
88     ml->last->next = mln;
89   }
90 
91   ml->last = mln;
92   ml->last->next = NULL;
93   ml->size++;
94 }
95 
96 
97 /*
98  * Initialize a multiple list node
99  */
mlist_node_init()100 mlist_node *mlist_node_init()
101 {
102   mlist_node *mln;
103 
104   mln = malloc(sizeof(mlist_node));
105   assert(mln);
106 
107   mln->value = NULL;
108   mln->prev = NULL;
109   mln->next = NULL;
110 
111   return mln;
112 }
113 
114 
115 /*
116  * Free a multiple list node
117  */
mlist_node_free(mlist * ml,mlist_node * mln)118 void mlist_node_free(mlist * ml, mlist_node * mln)
119 {
120   assert(mln);
121   assert(ml);
122 
123   if (mln->prev)
124     mln->prev = NULL;
125 
126   if (mln->next) {
127     ml->first = mln->next;
128     mln->next = NULL;
129   } else
130     ml->first = NULL;
131 
132   if (mln->value) list_free(mln->value);
133 
134   free(mln);
135   mln = NULL;
136 }
137 
138 
139 /*
140  * Trunk an initial buffer into several pieces upon two separators
141  * Inside multiple list, each element is separated by a comma
142  * Careful returned multiple list must then be free with mlist_free()
143  */
mlist_explode(char separator_start,char separator_end,buffer * value)144 mlist *mlist_explode(char separator_start, char separator_end, buffer * value)
145 {
146   size_t i;
147   mlist *ml;
148   list *l;
149   buffer *buf;
150 
151   assert(value);
152 
153   ml = mlist_init();
154 
155   /* if first char doesn't match separator, mlist contains only one element */
156   if (value->buf[0] != separator_start) {
157     /* according to wfs specification, elements inside a multiple list
158        are separated by a comma */
159     l = list_explode(',', value);
160     mlist_add(ml, l);
161   } else {
162     buf = buffer_init();
163 
164     for (i = 1; i < value->use; i++)
165       if (value->buf[i] == separator_end) {
166         /* explode the mlist's element */
167         l = list_explode(',', buf);
168         /* add the list to the multiple list */
169         mlist_add(ml, l);
170         buffer_free(buf);
171       } else if (value->buf[i] != separator_start) {
172         buffer_add(buf, value->buf[i]);
173       }
174     /* separator start */
175       else
176         buf = buffer_init();
177 
178   }
179 
180   return ml;
181 }
182 
183 
184 #ifdef OWS_DEBUG
185 /*
186  * Flush a mlist to a given file
187  * (mainly to debug purpose)
188  */
mlist_flush(const mlist * ml,FILE * output)189 void mlist_flush(const mlist * ml, FILE * output)
190 {
191   mlist_node *mln;
192 
193   assert(ml);
194   assert(output);
195 
196   for (mln = ml->first ; mln ; mln = mln->next) {
197     fprintf(output, "(\n");
198     list_flush(mln->value, output);
199     fprintf(output, ")\n");
200   }
201 }
202 #endif
203 
204 
205 /*
206  * vim: expandtab sw=4 ts=4
207  */
208