Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gnulib-local / lib / libcroco / 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 <config.h>
23 #include <string.h>
24 #include "cr-prop-list.h"
25
26 #define PRIVATE(a_obj) (a_obj)->priv
27
28 struct _CRPropListPriv {
29         CRString *prop;
30         CRDeclaration *decl;
31         CRPropList *next;
32         CRPropList *prev;
33 };
34
35 static CRPropList *cr_prop_list_allocate (void);
36
37 /**
38  *Default allocator of CRPropList
39  *@return the newly allocated CRPropList or NULL
40  *if an error arises.
41  */
42 static CRPropList *
43 cr_prop_list_allocate (void)
44 {
45         CRPropList *result = NULL;
46
47         result = g_try_malloc (sizeof (CRPropList));
48         if (!result) {
49                 cr_utils_trace_info ("could not allocate CRPropList");
50                 return NULL;
51         }
52         memset (result, 0, sizeof (CRPropList));
53         PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
54         if (!result) {
55                 cr_utils_trace_info ("could not allocate CRPropListPriv");
56                 g_free (result);
57                 return NULL;
58         }
59         memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
60         return result;
61 }
62
63 /****************
64  *public methods
65  ***************/
66
67 /**
68  * cr_prop_list_append:
69  *@a_this: the current instance of #CRPropList
70  *@a_to_append: the property list to append
71  *
72  *Appends a property list to the current one.
73  *
74  *Returns the resulting prop list, or NULL if an error
75  *occured
76  */
77 CRPropList *
78 cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
79 {
80         CRPropList *cur = NULL;
81
82         g_return_val_if_fail (a_to_append, NULL);
83
84         if (!a_this)
85                 return a_to_append;
86
87         /*go fetch the last element of the list */
88         for (cur = a_this;
89              cur && PRIVATE (cur) && PRIVATE (cur)->next;
90              cur = PRIVATE (cur)->next) ;
91         g_return_val_if_fail (cur, NULL);
92         PRIVATE (cur)->next = a_to_append;
93         PRIVATE (a_to_append)->prev = cur;
94         return a_this;
95 }
96
97 /**
98  * cr_prop_list_append2:
99  *Appends a pair of prop/declaration to
100  *the current prop list.
101  *@a_this: the current instance of #CRPropList
102  *@a_prop: the property to consider
103  *@a_decl: the declaration to consider
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 * 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  * Returns CR_OK upon successful completion, an error code otherwise.
224  */
225 enum CRStatus
226 cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
227 {
228         g_return_val_if_fail (a_this && PRIVATE (a_this)
229                               && a_decl, CR_BAD_PARAM_ERROR);
230
231         PRIVATE (a_this)->decl = a_decl;
232         return CR_OK;
233 }
234
235 /**
236  * cr_prop_list_get_decl:
237  * @a_this: the current instance of #CRPropList
238  * @a_decl: out parameter. The property value
239  * Returns CR_OK upon successful completion.
240  */
241 enum CRStatus
242 cr_prop_list_get_decl (CRPropList * a_this, CRDeclaration ** a_decl)
243 {
244         g_return_val_if_fail (a_this && PRIVATE (a_this)
245                               && a_decl, CR_BAD_PARAM_ERROR);
246
247         *a_decl = PRIVATE (a_this)->decl;
248         return CR_OK;
249 }
250
251 /**
252  * cr_prop_list_lookup_prop:
253  *@a_this: the current instance of #CRPropList
254  *@a_prop: the property to lookup
255  *@a_prop_list: out parameter. The property/declaration
256  *pair found (if and only if the function returned code if CR_OK)
257  *
258  *Lookup a given property/declaration pair
259  *
260  *Returns CR_OK if a prop/decl pair has been found,
261  *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
262  *bad happens.
263  */
264 enum CRStatus
265 cr_prop_list_lookup_prop (CRPropList * a_this,
266                           CRString * a_prop, CRPropList ** a_pair)
267 {
268         CRPropList *cur = NULL;
269
270         g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
271
272         if (!a_this)
273                 return CR_VALUE_NOT_FOUND_ERROR;
274
275         g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
276
277         for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
278                 if (PRIVATE (cur)->prop
279                     && PRIVATE (cur)->prop->stryng
280                     && PRIVATE (cur)->prop->stryng->str
281                     && a_prop->stryng
282                     && a_prop->stryng->str
283                     && !strcmp (PRIVATE (cur)->prop->stryng->str, 
284                                 a_prop->stryng->str))
285                         break;
286         }
287
288         if (cur) {
289                 *a_pair = cur;
290                 return CR_OK;
291         }
292
293         return CR_VALUE_NOT_FOUND_ERROR;
294 }
295
296 /**
297  * cr_prop_list_get_next:
298  *@a_this: the current instance of CRPropList
299  *
300  *Gets the next prop/decl pair in the list
301  *
302  *Returns the next prop/declaration pair of the list, 
303  *or NULL if we reached end of list (or if an error occurs)
304  */
305 CRPropList *
306 cr_prop_list_get_next (CRPropList * a_this)
307 {
308         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
309
310         return PRIVATE (a_this)->next;
311 }
312
313 /**
314  * cr_prop_list_get_prev:
315  *@a_this: the current instance of CRPropList
316  *
317  *Gets the previous prop/decl pair in the list
318  *
319  *Returns the previous prop/declaration pair of the list, 
320  *or NULL if we reached end of list (or if an error occurs)
321  */
322 CRPropList *
323 cr_prop_list_get_prev (CRPropList * a_this)
324 {
325         g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
326
327         return PRIVATE (a_this)->prev;
328 }
329
330 /**
331  * cr_prop_list_unlink:
332  *@a_this: the current list of prop/decl pairs
333  *@a_pair: the prop/decl pair to unlink.
334  *
335  *Unlinks a prop/decl pair from the list
336  *
337  *Returns the new list or NULL in case of an error.
338  */
339 CRPropList *
340 cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
341 {
342         CRPropList *prev = NULL,
343                 *next = NULL;
344
345         g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
346
347         /*some sanity checks */
348         if (PRIVATE (a_pair)->next) {
349                 next = PRIVATE (a_pair)->next;
350                 g_return_val_if_fail (PRIVATE (next), NULL);
351                 g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
352         }
353         if (PRIVATE (a_pair)->prev) {
354                 prev = PRIVATE (a_pair)->prev;
355                 g_return_val_if_fail (PRIVATE (prev), NULL);
356                 g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
357         }
358         if (prev) {
359                 PRIVATE (prev)->next = next;
360         }
361         if (next) {
362                 PRIVATE (next)->prev = prev;
363         }
364         PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
365         if (a_this == a_pair) {
366                 if (next)
367                         return next;
368                 return NULL;
369         }
370         return a_this;
371 }
372
373 /**
374  * cr_prop_list_detroy:
375  * @a_this: the current instance of #CRPropList
376  */
377 void
378 cr_prop_list_destroy (CRPropList * a_this)
379 {
380         CRPropList *tail = NULL,
381                 *cur = NULL;
382
383         g_return_if_fail (a_this && PRIVATE (a_this));
384
385         for (tail = a_this;
386              tail && PRIVATE (tail) && PRIVATE (tail)->next;
387              tail = cr_prop_list_get_next (tail)) ;
388         g_return_if_fail (tail);
389
390         cur = tail;
391
392         while (cur) {
393                 tail = PRIVATE (cur)->prev;
394                 if (tail && PRIVATE (tail))
395                         PRIVATE (tail)->next = NULL;
396                 PRIVATE (cur)->prev = NULL;
397                 g_free (PRIVATE (cur));
398                 PRIVATE (cur) = NULL;
399                 g_free (cur);
400                 cur = tail;
401         }
402 }