"Initial commit to Gerrit"
[profile/ivi/libcroco.git] / src / cr-selector.c
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  * This file is part of The Croco Library
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of version 2.1 of the GNU Lesser General Public
8  * License as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  *
20  * See COPYRIGHTS file for copyright information.
21  */
22
23 #include <string.h>
24 #include "cr-selector.h"
25 #include "cr-parser.h"
26
27 /**
28  * cr_selector_new:
29  *
30  *@a_simple_sel: the initial simple selector list
31  *of the current instance of #CRSelector.
32  *
33  *Creates a new instance of #CRSelector.
34  *
35  *Returns the newly built instance of #CRSelector, or
36  *NULL in case of failure.
37  */
38 CRSelector *
39 cr_selector_new (CRSimpleSel * a_simple_sel)
40 {
41         CRSelector *result = NULL;
42
43         result = g_try_malloc (sizeof (CRSelector));
44         if (!result) {
45                 cr_utils_trace_info ("Out of memory");
46                 return NULL;
47         }
48         memset (result, 0, sizeof (CRSelector));
49         result->simple_sel = a_simple_sel;
50         return result;
51 }
52
53 CRSelector *
54 cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
55 {
56         CRParser *parser = NULL;
57
58         g_return_val_if_fail (a_char_buf, NULL);
59
60         parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen (a_char_buf),
61                                          a_enc, FALSE);
62         g_return_val_if_fail (parser, NULL);
63
64         return NULL;
65 }
66
67 /**
68  * cr_selector_append:
69  *
70  *@a_this: the current instance of #CRSelector.
71  *@a_new: the instance of #CRSelector to be appended.
72  *
73  *Appends a new instance of #CRSelector to the current selector list.
74  *
75  *Returns the new list.
76  */
77 CRSelector *
78 cr_selector_append (CRSelector * a_this, CRSelector * a_new)
79 {
80         CRSelector *cur = NULL;
81
82         if (!a_this) {
83                 return a_new;
84         }
85
86         /*walk forward the list headed by a_this to get the list tail */
87         for (cur = a_this; cur && cur->next; cur = cur->next) ;
88
89         cur->next = a_new;
90         a_new->prev = cur;
91
92         return a_this;
93 }
94
95 /**
96  * cr_selector_prepend:
97  *
98  *@a_this: the current instance of #CRSelector list.
99  *@a_new: the instance of #CRSelector.
100  *
101  *Prepends an element to the #CRSelector list.
102  * 
103  *Returns the new list.
104  */
105 CRSelector *
106 cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
107 {
108         CRSelector *cur = NULL;
109
110         a_new->next = a_this;
111         a_this->prev = a_new;
112
113         for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
114
115         return cur;
116 }
117
118 /**
119  * cr_selector_append_simple_sel:
120  *
121  *@a_this: the current instance of #CRSelector.
122  *@a_simple_sel: the simple selector to append.
123  *
124  *append a simple selector to the current #CRSelector list.
125  *
126  *Returns the new list or NULL in case of failure.
127  */
128 CRSelector *
129 cr_selector_append_simple_sel (CRSelector * a_this,
130                                CRSimpleSel * a_simple_sel)
131 {
132         CRSelector *selector = NULL;
133
134         selector = cr_selector_new (a_simple_sel);
135         g_return_val_if_fail (selector, NULL);
136
137         return cr_selector_append (a_this, selector);
138 }
139
140 guchar *
141 cr_selector_to_string (CRSelector const * a_this)
142 {
143         guchar *result = NULL;
144         GString *str_buf = NULL;
145
146         str_buf = g_string_new (NULL);
147         g_return_val_if_fail (str_buf, NULL);
148
149         if (a_this) {
150                 CRSelector const *cur = NULL;
151
152                 for (cur = a_this; cur; cur = cur->next) {
153                         if (cur->simple_sel) {
154                                 guchar *tmp_str = NULL;
155
156                                 tmp_str = cr_simple_sel_to_string
157                                         (cur->simple_sel);
158
159                                 if (tmp_str) {
160                                         if (cur->prev)
161                                                 g_string_append (str_buf, 
162                                                                  ", ");
163
164                                         g_string_append (str_buf, tmp_str);
165
166                                         g_free (tmp_str);
167                                         tmp_str = NULL;
168                                 }
169                         }
170                 }
171         }
172
173         if (str_buf) {
174                 result = str_buf->str;
175                 g_string_free (str_buf, FALSE);
176                 str_buf = NULL;
177         }
178
179         return result;
180 }
181
182 /**
183  * cr_selector_dump:
184  *
185  *@a_this: the current instance of #CRSelector.
186  *@a_fp: the destination file.
187  *
188  *Serializes the current instance of #CRSelector to a file.
189  */
190 void
191 cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
192 {
193         guchar *tmp_buf = NULL;
194
195         if (a_this) {
196                 tmp_buf = cr_selector_to_string (a_this);
197                 if (tmp_buf) {
198                         fprintf (a_fp, "%s", tmp_buf);
199                         g_free (tmp_buf);
200                         tmp_buf = NULL;
201                 }
202         }
203 }
204
205 /**
206  * cr_selector_ref:
207  *
208  *@a_this: the current instance of #CRSelector.
209  *
210  *Increments the ref count of the current instance
211  *of #CRSelector.
212  */
213 void
214 cr_selector_ref (CRSelector * a_this)
215 {
216         g_return_if_fail (a_this);
217
218         a_this->ref_count++;
219 }
220
221 /**
222  * cr_selector_unref:
223  *
224  *@a_this: the current instance of #CRSelector.
225  *
226  *Decrements the ref count of the current instance of
227  *#CRSelector.
228  *If the ref count reaches zero, the current instance of
229  *#CRSelector is destroyed.
230  *
231  *Returns TRUE if this function destroyed the current instance
232  *of #CRSelector, FALSE otherwise.
233  */
234 gboolean
235 cr_selector_unref (CRSelector * a_this)
236 {
237         g_return_val_if_fail (a_this, FALSE);
238
239         if (a_this->ref_count) {
240                 a_this->ref_count--;
241         }
242
243         if (a_this->ref_count == 0) {
244                 cr_selector_destroy (a_this);
245                 return TRUE;
246         }
247
248         return FALSE;
249 }
250
251 /**
252  * cr_selector_destroy:
253  *
254  *@a_this: the current instance of #CRSelector.
255  *
256  *Destroys the selector list.
257  */
258 void
259 cr_selector_destroy (CRSelector * a_this)
260 {
261         CRSelector *cur = NULL;
262
263         g_return_if_fail (a_this);
264
265         /*
266          *go and get the list tail. In the same time, free
267          *all the simple selectors contained in the list.
268          */
269         for (cur = a_this; cur && cur->next; cur = cur->next) {
270                 if (cur->simple_sel) {
271                         cr_simple_sel_destroy (cur->simple_sel);
272                         cur->simple_sel = NULL;
273                 }
274         }
275
276         if (cur) {
277                 if (cur->simple_sel) {
278                         cr_simple_sel_destroy (cur->simple_sel);
279                         cur->simple_sel = NULL;
280                 }
281         }
282
283         /*in case the list has only one element */
284         if (cur && !cur->prev) {
285                 g_free (cur);
286                 return;
287         }
288
289         /*walk backward the list and free each "next element" */
290         for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
291                 if (cur->next) {
292                         g_free (cur->next);
293                         cur->next = NULL;
294                 }
295         }
296
297         if (!cur)
298                 return;
299
300         if (cur->next) {
301                 g_free (cur->next);
302                 cur->next = NULL;
303         }
304
305         g_free (cur);
306 }