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 = NULL;
46 result = g_try_malloc (sizeof (CRPropList));
47 if (!result) {
48 cr_utils_trace_info ("could not allocate CRPropList");
49 return NULL;
50 }
51 memset (result, 0, sizeof (CRPropList));
52 PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
53 if (!result) {
54 cr_utils_trace_info ("could not allocate CRPropListPriv");
55 g_free (result);
56 return NULL;
57 }
58 memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
59 return result;
60 }
62 /****************
63 *public methods
64 ***************/
66 /**
67 *Appends a property list to the current one.
68 *@param a_this the current instance of #CRPropList
69 *@param a_to_append the property list to append
70 *@return the resulting prop list, or NULL if an error
71 *occured
72 */
73 CRPropList *
74 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
75 {
76 CRPropList *cur = NULL;
78 g_return_val_if_fail (a_to_append, NULL);
80 if (!a_this)
81 return a_to_append;
83 /*go fetch the last element of the list */
84 for (cur = a_this;
85 cur && PRIVATE (cur) && PRIVATE (cur)->next;
86 cur = PRIVATE (cur)->next) ;
87 g_return_val_if_fail (cur, NULL);
88 PRIVATE (cur)->next = a_to_append;
89 PRIVATE (a_to_append)->prev = cur;
90 return a_this;
91 }
93 /**
94 *Appends a pair of prop/declaration to
95 *the current prop list.
96 *@param a_this the current instance of #CRPropList
97 *@param a_prop the property to consider
98 *@param a_decl the declaration to consider
99 *@return the resulting property list, or NULL in case
100 *of an error.
101 */
102 CRPropList *
103 cr_prop_list_append2 (CRPropList * a_this,
104 CRString * a_prop,
105 CRDeclaration * a_decl)
106 {
107 CRPropList *list = NULL,
108 *result = NULL;
110 g_return_val_if_fail (a_prop && a_decl, NULL);
112 list = cr_prop_list_allocate ();
113 g_return_val_if_fail (list && PRIVATE (list), NULL);
115 PRIVATE (list)->prop = a_prop;
116 PRIVATE (list)->decl = a_decl;
118 result = cr_prop_list_append (a_this, list);
119 return result;
120 }
122 /**
123 *Prepends a list to the current list
124 *@param a_this the current instance of #CRPropList
125 *@param the new list to prepend.
126 */
127 CRPropList *
128 cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
129 {
130 CRPropList *cur = NULL;
132 g_return_val_if_fail (a_to_prepend, NULL);
134 if (!a_this)
135 return a_to_prepend;
137 for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
138 cur = PRIVATE (cur)->next) ;
139 g_return_val_if_fail (cur, NULL);
140 PRIVATE (cur)->next = a_this;
141 PRIVATE (a_this)->prev = cur;
142 return a_to_prepend;
143 }
145 /**
146 *Prepends a list to the current list
147 *@param a_this the current instance of #CRPropList
148 *@param the new list to prepend.
149 */
150 CRPropList *
151 cr_prop_list_prepend2 (CRPropList * a_this,
152 CRString * a_prop, CRDeclaration * a_decl)
153 {
154 CRPropList *list = NULL,
155 *result = NULL;
157 g_return_val_if_fail (a_this && PRIVATE (a_this)
158 && a_prop && a_decl, NULL);
160 list = cr_prop_list_allocate ();
161 g_return_val_if_fail (list, NULL);
162 PRIVATE (list)->prop = a_prop;
163 PRIVATE (list)->decl = a_decl;
164 result = cr_prop_list_prepend (a_this, list);
165 return result;
166 }
168 /**
169 *Sets the property of a CRPropList
170 *@param a_this the current instance of #CRPropList
171 *@param a_prop the property to set
172 */
173 enum CRStatus
174 cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
175 {
176 g_return_val_if_fail (a_this && PRIVATE (a_this)
177 && a_prop, CR_BAD_PARAM_ERROR);
179 PRIVATE (a_this)->prop = a_prop;
180 return CR_OK;
181 }
183 /**
184 *Getter of the property associated to the current instance
185 *of #CRPropList
186 *@param a_this the current instance of #CRPropList
187 *@param a_prop out parameter. The returned property
188 *@return CR_OK upon successful completion, an error code
189 *otherwise.
190 */
191 enum CRStatus
192 cr_prop_list_get_prop (CRPropList * a_this, CRString ** a_prop)
193 {
194 g_return_val_if_fail (a_this && PRIVATE (a_this)
195 && a_prop, CR_BAD_PARAM_ERROR);
197 *a_prop = PRIVATE (a_this)->prop;
198 return CR_OK;
199 }
201 enum CRStatus
202 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
203 {
204 g_return_val_if_fail (a_this && PRIVATE (a_this)
205 && a_decl, CR_BAD_PARAM_ERROR);
207 PRIVATE (a_this)->decl = a_decl;
208 return CR_OK;
209 }
211 enum CRStatus
212 cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl)
213 {
214 g_return_val_if_fail (a_this && PRIVATE (a_this)
215 && a_decl, CR_BAD_PARAM_ERROR);
217 *a_decl = PRIVATE (a_this)->decl;
218 return CR_OK;
219 }
221 /**
222 *Lookup a given property/declaration pair
223 *@param a_this the current instance of #CRPropList
224 *@param a_prop the property to lookup
225 *@param a_prop_list out parameter. The property/declaration
226 *pair found (if and only if the function returned code if CR_OK)
227 *@return CR_OK if a prop/decl pair has been found,
228 *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
229 *bad happens.
230 */
231 enum CRStatus
232 cr_prop_list_lookup_prop (CRPropList * a_this,
233 CRString * a_prop, CRPropList ** a_pair)
234 {
235 CRPropList *cur = NULL;
237 g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
239 if (!a_this)
240 return CR_VALUE_NOT_FOUND_ERROR;
242 g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
244 for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
245 if (PRIVATE (cur)->prop
246 && PRIVATE (cur)->prop->stryng
247 && PRIVATE (cur)->prop->stryng->str
248 && a_prop->stryng
249 && a_prop->stryng->str
250 && !strcmp (PRIVATE (cur)->prop->stryng->str,
251 a_prop->stryng->str))
252 break;
253 }
255 if (cur) {
256 *a_pair = cur;
257 return CR_OK;
258 }
260 return CR_VALUE_NOT_FOUND_ERROR;
261 }
263 /**
264 *Gets the next prop/decl pair in the list
265 *@param a_this the current instance of CRPropList
266 *@param the next prop/decl pair, or NULL if we
267 *reached the end of the list.
268 *@return the next prop/declaration pair of the list,
269 *or NULL if we reached end of list (or if an error occurs)
270 */
271 CRPropList *
272 cr_prop_list_get_next (CRPropList * a_this)
273 {
274 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
276 return PRIVATE (a_this)->next;
277 }
279 /**
280 *Gets the previous prop/decl pair in the list
281 *@param a_this the current instance of CRPropList
282 *@param the previous prop/decl pair, or NULL if we
283 *reached the end of the list.
284 *@return the previous prop/declaration pair of the list,
285 *or NULL if we reached end of list (or if an error occurs)
286 */
287 CRPropList *
288 cr_prop_list_get_prev (CRPropList * a_this)
289 {
290 g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
292 return PRIVATE (a_this)->prev;
293 }
295 /**
296 *Unlinks a prop/decl pair from the list
297 *@param a_this the current list of prop/decl pairs
298 *@param a_pair the prop/decl pair to unlink.
299 *@return the new list or NULL in case of an error.
300 */
301 CRPropList *
302 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
303 {
304 CRPropList *prev = NULL,
305 *next = NULL;
307 g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
309 /*some sanity checks */
310 if (PRIVATE (a_pair)->next) {
311 next = PRIVATE (a_pair)->next;
312 g_return_val_if_fail (PRIVATE (next), NULL);
313 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
314 }
315 if (PRIVATE (a_pair)->prev) {
316 prev = PRIVATE (a_pair)->prev;
317 g_return_val_if_fail (PRIVATE (prev), NULL);
318 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
319 }
320 if (prev) {
321 PRIVATE (prev)->next = next;
322 }
323 if (next) {
324 PRIVATE (next)->prev = prev;
325 }
326 PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
327 if (a_this == a_pair) {
328 if (next)
329 return next;
330 return NULL;
331 }
332 return a_this;
333 }
335 void
336 cr_prop_list_destroy (CRPropList * a_this)
337 {
338 CRPropList *tail = NULL,
339 *cur = NULL;
341 g_return_if_fail (a_this && PRIVATE (a_this));
343 for (tail = a_this;
344 tail && PRIVATE (tail) && PRIVATE (tail)->next;
345 tail = cr_prop_list_get_next (tail)) ;
346 g_return_if_fail (tail);
348 cur = tail;
350 while (cur) {
351 tail = PRIVATE (cur)->prev;
352 if (tail && PRIVATE (tail))
353 PRIVATE (tail)->next = NULL;
354 PRIVATE (cur)->prev = NULL;
355 g_free (PRIVATE (cur));
356 PRIVATE (cur) = NULL;
357 g_free (cur);
358 cur = tail;
359 }
360 }