1 /*
2 * This file is part of The Croco Library
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2.1 of the GNU Lesser General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
16 * USA
17 *
18 * Author: Dodji Seketeli
19 * See COPYRIGHTS file for copyrights information.
20 */
22 #include <string.h>
23 #include "cr-prop-list.h"
25 #define PRIVATE(a_obj) (a_obj)->priv
27 struct _CRPropListPriv {
28 CRString *prop;
29 CRDeclaration *decl;
30 CRPropList *next;
31 CRPropList *prev;
32 };
34 static CRPropList *cr_prop_list_allocate (void);
36 /**
37 *Default allocator of CRPropList
38 *@return the newly allocated CRPropList or NULL
39 *if an error arises.
40 */
41 static CRPropList *
42 cr_prop_list_allocate (void)
43 {
44 CRPropList *result = (CRPropList *)g_try_malloc (sizeof (CRPropList));
45 if (!result) {
46 cr_utils_trace_info ("could not allocate CRPropList");
47 return NULL;
48 }
49 memset (result, 0, sizeof (CRPropList));
50 PRIVATE (result) = (CRPropListPriv *)g_try_malloc (sizeof (CRPropListPriv));
51 if (!result) {
52 cr_utils_trace_info ("could not allocate CRPropListPriv");
53 g_free (result);
54 return NULL;
55 }
56 memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
57 return result;
58 }
60 /****************
61 *public methods
62 ***************/
64 /**
65 *Appends a property list to the current one.
66 *@param a_this the current instance of #CRPropList
67 *@param a_to_append the property list to append
68 *@return the resulting prop list, or NULL if an error
69 *occured
70 */
71 CRPropList *
72 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
73 {
74 CRPropList *cur = NULL;
76 g_return_val_if_fail (a_to_append, NULL);
78 if (!a_this)
79 return a_to_append;
81 /*go fetch the last element of the list */
82 for (cur = a_this;
83 cur && PRIVATE (cur) && PRIVATE (cur)->next;
84 cur = PRIVATE (cur)->next) ;
85 g_return_val_if_fail (cur, NULL);
86 PRIVATE (cur)->next = a_to_append;
87 PRIVATE (a_to_append)->prev = cur;
88 return a_this;
89 }
91 /**
92 *Appends a pair of prop/declaration to
93 *the current prop list.
94 *@param a_this the current instance of #CRPropList
95 *@param a_prop the property to consider
96 *@param a_decl the declaration to consider
97 *@return the resulting property list, or NULL in case
98 *of an error.
99 */
100 CRPropList *
101 cr_prop_list_append2 (CRPropList * a_this,
102 CRString * a_prop,
103 CRDeclaration * a_decl)
104 {
105 CRPropList *list = NULL,
106 *result = NULL;
108 g_return_val_if_fail (a_prop && a_decl, NULL);
110 list = cr_prop_list_allocate ();
111 g_return_val_if_fail (list && PRIVATE (list), NULL);
113 PRIVATE (list)->prop = a_prop;
114 PRIVATE (list)->decl = a_decl;
116 result = cr_prop_list_append (a_this, list);
117 return result;
118 }
120 /**
121 *Prepends a list to the current list
122 *@param a_this the current instance of #CRPropList
123 *@param the new list to prepend.
124 */
125 CRPropList *
126 cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
127 {
128 CRPropList *cur = NULL;
130 g_return_val_if_fail (a_to_prepend, NULL);
132 if (!a_this)
133 return a_to_prepend;
135 for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
136 cur = PRIVATE (cur)->next) ;
137 g_return_val_if_fail (cur, NULL);
138 PRIVATE (cur)->next = a_this;
139 PRIVATE (a_this)->prev = cur;
140 return a_to_prepend;
141 }
143 /**
144 *Prepends a list to the current list
145 *@param a_this the current instance of #CRPropList
146 *@param the new list to prepend.
147 */
148 CRPropList *
149 cr_prop_list_prepend2 (CRPropList * a_this,
150 CRString * a_prop, CRDeclaration * a_decl)
151 {
152 CRPropList *list = NULL,
153 *result = NULL;
155 g_return_val_if_fail (a_this && PRIVATE (a_this)
156 && a_prop && a_decl, NULL);
158 list = cr_prop_list_allocate ();
159 g_return_val_if_fail (list, NULL);
160 PRIVATE (list)->prop = a_prop;
161 PRIVATE (list)->decl = a_decl;
162 result = cr_prop_list_prepend (a_this, list);
163 return result;
164 }
166 /**
167 *Sets the property of a CRPropList
168 *@param a_this the current instance of #CRPropList
169 *@param a_prop the property to set
170 */
171 enum CRStatus
172 cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
173 {
174 g_return_val_if_fail (a_this && PRIVATE (a_this)
175 && a_prop, CR_BAD_PARAM_ERROR);
177 PRIVATE (a_this)->prop = a_prop;
178 return CR_OK;
179 }
181 /**
182 *Getter of the property associated to the current instance
183 *of #CRPropList
184 *@param a_this the current instance of #CRPropList
185 *@param a_prop out parameter. The returned property
186 *@return CR_OK upon successful completion, an error code
187 *otherwise.
188 */
189 enum CRStatus
190 cr_prop_list_get_prop (CRPropList * a_this, CRString ** a_prop)
191 {
192 g_return_val_if_fail (a_this && PRIVATE (a_this)
193 && a_prop, CR_BAD_PARAM_ERROR);
195 *a_prop = PRIVATE (a_this)->prop;
196 return CR_OK;
197 }
199 enum CRStatus
200 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
201 {
202 g_return_val_if_fail (a_this && PRIVATE (a_this)
203 && a_decl, CR_BAD_PARAM_ERROR);
205 PRIVATE (a_this)->decl = a_decl;
206 return CR_OK;
207 }
209 enum CRStatus
210 cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl)
211 {
212 g_return_val_if_fail (a_this && PRIVATE (a_this)
213 && a_decl, CR_BAD_PARAM_ERROR);
215 *a_decl = PRIVATE (a_this)->decl;
216 return CR_OK;
217 }
219 /**
220 *Lookup a given property/declaration pair
221 *@param a_this the current instance of #CRPropList
222 *@param a_prop the property to lookup
223 *@param a_prop_list out parameter. The property/declaration
224 *pair found (if and only if the function returned code if CR_OK)
225 *@return CR_OK if a prop/decl pair has been found,
226 *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
227 *bad happens.
228 */
229 enum CRStatus
230 cr_prop_list_lookup_prop (CRPropList * a_this,
231 CRString * a_prop, CRPropList ** a_pair)
232 {
233 CRPropList *cur = NULL;
235 g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
237 if (!a_this)
238 return CR_VALUE_NOT_FOUND_ERROR;
240 g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
242 for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
243 if (PRIVATE (cur)->prop
244 && PRIVATE (cur)->prop->stryng
245 && PRIVATE (cur)->prop->stryng->str
246 && a_prop->stryng
247 && a_prop->stryng->str
248 && !strcmp (PRIVATE (cur)->prop->stryng->str,
249 a_prop->stryng->str))
250 break;
251 }
253 if (cur) {
254 *a_pair = cur;
255 return CR_OK;
256 }
258 return CR_VALUE_NOT_FOUND_ERROR;
259 }
261 /**
262 *Gets the next prop/decl pair in the list
263 *@param a_this the current instance of CRPropList
264 *@param the next prop/decl pair, or NULL if we
265 *reached the end of the list.
266 *@return the next prop/declaration pair of the list,
267 *or NULL if we reached end of list (or if an error occurs)
268 */
269 CRPropList *
270 cr_prop_list_get_next (CRPropList * a_this)
271 {
272 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
274 return PRIVATE (a_this)->next;
275 }
277 /**
278 *Gets the previous prop/decl pair in the list
279 *@param a_this the current instance of CRPropList
280 *@param the previous prop/decl pair, or NULL if we
281 *reached the end of the list.
282 *@return the previous prop/declaration pair of the list,
283 *or NULL if we reached end of list (or if an error occurs)
284 */
285 CRPropList *
286 cr_prop_list_get_prev (CRPropList * a_this)
287 {
288 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
290 return PRIVATE (a_this)->prev;
291 }
293 /**
294 *Unlinks a prop/decl pair from the list
295 *@param a_this the current list of prop/decl pairs
296 *@param a_pair the prop/decl pair to unlink.
297 *@return the new list or NULL in case of an error.
298 */
299 CRPropList *
300 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
301 {
302 CRPropList *prev = NULL,
303 *next = NULL;
305 g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
307 /*some sanity checks */
308 if (PRIVATE (a_pair)->next) {
309 next = PRIVATE (a_pair)->next;
310 g_return_val_if_fail (PRIVATE (next), NULL);
311 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
312 }
313 if (PRIVATE (a_pair)->prev) {
314 prev = PRIVATE (a_pair)->prev;
315 g_return_val_if_fail (PRIVATE (prev), NULL);
316 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
317 }
318 if (prev) {
319 PRIVATE (prev)->next = next;
320 }
321 if (next) {
322 PRIVATE (next)->prev = prev;
323 }
324 PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
325 if (a_this == a_pair) {
326 if (next)
327 return next;
328 return NULL;
329 }
330 return a_this;
331 }
333 void
334 cr_prop_list_destroy (CRPropList * a_this)
335 {
336 CRPropList *tail = NULL,
337 *cur = NULL;
339 g_return_if_fail (a_this && PRIVATE (a_this));
341 for (tail = a_this;
342 tail && PRIVATE (tail) && PRIVATE (tail)->next;
343 tail = cr_prop_list_get_next (tail)) ;
344 g_return_if_fail (tail);
346 cur = tail;
348 while (cur) {
349 tail = PRIVATE (cur)->prev;
350 if (tail && PRIVATE (tail))
351 PRIVATE (tail)->next = NULL;
352 PRIVATE (cur)->prev = NULL;
353 g_free (PRIVATE (cur));
354 PRIVATE (cur) = NULL;
355 g_free (cur);
356 cur = tail;
357 }
358 }