"Initial commit to Gerrit"
[profile/ivi/libcroco.git] / src / cr-prop-list.c
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  */
21
22 #include <string.h>
23 #include "cr-prop-list.h"
24
25 #define PRIVATE(a_obj) (a_obj)->priv
26
27 struct _CRPropListPriv {
28         CRString *prop;
29         CRDeclaration *decl;
30         CRPropList *next;
31         CRPropList *prev;
32 };
33
34 static CRPropList *cr_prop_list_allocate (void);
35
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;
45
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 }
61
62 /****************
63  *public methods
64  ***************/
65
66 /**
67  * cr_prop_list_append:
68  *@a_this: the current instance of #CRPropList
69  *@a_to_append: the property list to append
70  *
71  *Appends a property list to the current one.
72  *
73  *Returns the resulting prop list, or NULL if an error
74  *occured
75  */
76 CRPropList *
77 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
78 {
79         CRPropList *cur = NULL;
80
81         g_return_val_if_fail (a_to_append, NULL);
82
83         if (!a_this)
84                 return a_to_append;
85
86         /*go fetch the last element of the list */
87         for (cur = a_this;
88              cur && PRIVATE (cur) && PRIVATE (cur)->next;
89              cur = PRIVATE (cur)->next) ;
90         g_return_val_if_fail (cur, NULL);
91         PRIVATE (cur)->next = a_to_append;
92         PRIVATE (a_to_append)->prev = cur;
93         return a_this;
94 }
95
96 /**
97  * cr_prop_list_append2:
98  *Appends a pair of prop/declaration to
99  *the current prop list.
100  *@a_this: the current instance of #CRPropList
101  *@a_prop: the property to consider
102  *@a_decl: the declaration to consider
103  *
104  *Returns the resulting property list, or NULL in case
105  *of an error.
106  */
107 CRPropList *
108 cr_prop_list_append2 (CRPropList * a_this,
109                       CRString * a_prop, 
110                       CRDeclaration * a_decl)
111 {
112         CRPropList *list = NULL,
113                 *result = NULL;
114
115         g_return_val_if_fail (a_prop && a_decl, NULL);
116
117         list = cr_prop_list_allocate ();
118         g_return_val_if_fail (list && PRIVATE (list), NULL);
119
120         PRIVATE (list)->prop = a_prop;
121         PRIVATE (list)->decl = a_decl;
122
123         result = cr_prop_list_append (a_this, list);
124         return result;
125 }
126
127 /**
128  * cr_prop_list_prepend:
129  *@a_this: the current instance of #CRPropList
130  *@a_to_prepend: the new list to prepend.
131  *
132  *Prepends a list to the current list
133  *Returns the new properties list.
134  */
135 CRPropList *
136 cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
137 {
138         CRPropList *cur = NULL;
139
140         g_return_val_if_fail (a_to_prepend, NULL);
141
142         if (!a_this)
143                 return a_to_prepend;
144
145         for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
146              cur = PRIVATE (cur)->next) ;
147         g_return_val_if_fail (cur, NULL);
148         PRIVATE (cur)->next = a_this;
149         PRIVATE (a_this)->prev = cur;
150         return a_to_prepend;
151 }
152
153 /**
154  * cr_prop_list_prepend2:
155  *@a_this: the current instance of #CRPropList
156  *@a_prop_name: property name to append
157  *@a_decl: the property value to append.
158  *
159  *Prepends a propertie to a list of properties 
160  *
161  *Returns the new property list.
162  */
163 CRPropList *
164 cr_prop_list_prepend2 (CRPropList * a_this,
165                        CRString * a_prop_name, CRDeclaration * a_decl)
166 {
167         CRPropList *list = NULL,
168                 *result = NULL;
169
170         g_return_val_if_fail (a_this && PRIVATE (a_this)
171                               && a_prop_name && a_decl, NULL);
172
173         list = cr_prop_list_allocate ();
174         g_return_val_if_fail (list, NULL);
175         PRIVATE (list)->prop = a_prop_name;
176         PRIVATE (list)->decl = a_decl;
177         result = cr_prop_list_prepend (a_this, list);
178         return result;
179 }
180
181 /**
182  * cr_prop_list_set_prop:
183  *@a_this: the current instance of #CRPropList
184  *@a_prop: the property to set
185  *
186  *Sets the property of a CRPropList
187  */
188 enum CRStatus
189 cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
190 {
191         g_return_val_if_fail (a_this && PRIVATE (a_this)
192                               && a_prop, CR_BAD_PARAM_ERROR);
193
194         PRIVATE (a_this)->prop = a_prop;
195         return CR_OK;
196 }
197
198 /**
199  * cr_prop_list_get_prop:
200  *@a_this: the current instance of #CRPropList
201  *@a_prop: out parameter. The returned property
202  *
203  *Getter of the property associated to the current instance
204  *of #CRPropList
205  *
206  *Returns CR_OK upon successful completion, an error code
207  *otherwise.
208  */
209 enum CRStatus
210 cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
211 {
212         g_return_val_if_fail (a_this && PRIVATE (a_this)
213                               && a_prop, CR_BAD_PARAM_ERROR);
214
215         *a_prop = PRIVATE (a_this)->prop;
216         return CR_OK;
217 }
218
219 /**
220  * cr_prop_list_set_decl:
221  * @a_this: the current instance of #CRPropList
222  * @a_decl: the new property value.
223  *
224  * Returns CR_OK upon successful completion, an error code otherwise.
225  */
226 enum CRStatus
227 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
228 {
229         g_return_val_if_fail (a_this && PRIVATE (a_this)
230                               && a_decl, CR_BAD_PARAM_ERROR);
231
232         PRIVATE (a_this)->decl = a_decl;
233         return CR_OK;
234 }
235
236 /**
237  * cr_prop_list_get_decl:
238  * @a_this: the current instance of #CRPropList
239  * @a_decl: out parameter. The property value
240  *
241  * Returns CR_OK upon successful completion.
242  */
243 enum CRStatus
244 cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
245 {
246         g_return_val_if_fail (a_this && PRIVATE (a_this)
247                               && a_decl, CR_BAD_PARAM_ERROR);
248
249         *a_decl = PRIVATE (a_this)->decl;
250         return CR_OK;
251 }
252
253 /**
254  * cr_prop_list_lookup_prop:
255  *@a_this: the current instance of #CRPropList
256  *@a_prop: the property to lookup
257  *@a_prop_list: out parameter. The property/declaration
258  *pair found (if and only if the function returned code if CR_OK)
259  *
260  *Lookup a given property/declaration pair
261  *
262  *Returns CR_OK if a prop/decl pair has been found,
263  *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
264  *bad happens.
265  */
266 enum CRStatus
267 cr_prop_list_lookup_prop (CRPropList * a_this,
268                           CRString * a_prop, CRPropList ** a_pair)
269 {
270         CRPropList *cur = NULL;
271
272         g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
273
274         if (!a_this)
275                 return CR_VALUE_NOT_FOUND_ERROR;
276
277         g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
278
279         for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
280                 if (PRIVATE (cur)->prop
281                     && PRIVATE (cur)->prop->stryng
282                     && PRIVATE (cur)->prop->stryng->str
283                     && a_prop->stryng
284                     && a_prop->stryng->str
285                     && !strcmp (PRIVATE (cur)->prop->stryng->str, 
286                                 a_prop->stryng->str))
287                         break;
288         }
289
290         if (cur) {
291                 *a_pair = cur;
292                 return CR_OK;
293         }
294
295         return CR_VALUE_NOT_FOUND_ERROR;
296 }
297
298 /**
299  * cr_prop_list_get_next:
300  *@a_this: the current instance of CRPropList
301  *
302  *Gets the next prop/decl pair in the list
303  *
304  *Returns the next prop/declaration pair of the list, 
305  *or NULL if we reached end of list (or if an error occurs)
306  */
307 CRPropList *
308 cr_prop_list_get_next (CRPropList * a_this)
309 {
310         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
311
312         return PRIVATE (a_this)->next;
313 }
314
315 /**
316  * cr_prop_list_get_prev:
317  *@a_this: the current instance of CRPropList
318  *
319  *Gets the previous prop/decl pair in the list
320  *
321  *Returns the previous prop/declaration pair of the list, 
322  *or NULL if we reached end of list (or if an error occurs)
323  */
324 CRPropList *
325 cr_prop_list_get_prev (CRPropList * a_this)
326 {
327         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
328
329         return PRIVATE (a_this)->prev;
330 }
331
332 /**
333  * cr_prop_list_unlink:
334  *@a_this: the current list of prop/decl pairs
335  *@a_pair: the prop/decl pair to unlink.
336  *
337  *Unlinks a prop/decl pair from the list
338  *
339  *Returns the new list or NULL in case of an error.
340  */
341 CRPropList *
342 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
343 {
344         CRPropList *prev = NULL,
345                 *next = NULL;
346
347         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
348
349         /*some sanity checks */
350         if (PRIVATE (a_pair)->next) {
351                 next = PRIVATE (a_pair)->next;
352                 g_return_val_if_fail (PRIVATE (next), NULL);
353                 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
354         }
355         if (PRIVATE (a_pair)->prev) {
356                 prev = PRIVATE (a_pair)->prev;
357                 g_return_val_if_fail (PRIVATE (prev), NULL);
358                 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
359         }
360         if (prev) {
361                 PRIVATE (prev)->next = next;
362         }
363         if (next) {
364                 PRIVATE (next)->prev = prev;
365         }
366         PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
367         if (a_this == a_pair) {
368                 if (next)
369                         return next;
370                 return NULL;
371         }
372         return a_this;
373 }
374
375 /**
376  * cr_prop_list_destroy:
377  * @a_this: the current instance of #CRPropList
378  */
379 void
380 cr_prop_list_destroy (CRPropList * a_this)
381 {
382         CRPropList *tail = NULL,
383                 *cur = NULL;
384
385         g_return_if_fail (a_this && PRIVATE (a_this));
386
387         for (tail = a_this;
388              tail && PRIVATE (tail) && PRIVATE (tail)->next;
389              tail = cr_prop_list_get_next (tail)) ;
390         g_return_if_fail (tail);
391
392         cur = tail;
393
394         while (cur) {
395                 tail = PRIVATE (cur)->prev;
396                 if (tail && PRIVATE (tail))
397                         PRIVATE (tail)->next = NULL;
398                 PRIVATE (cur)->prev = NULL;
399                 g_free (PRIVATE (cur));
400                 PRIVATE (cur) = NULL;
401                 g_free (cur);
402                 cur = tail;
403         }
404 }