1 /* -*- Mode: C; indent-tabs-mode: ni; c-basic-offset: 8 -*- */
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 */
23 #include <string.h>
24 #include "cr-selector.h"
25 #include "cr-parser.h"
27 /**
28 *Creates a new instance of #CRSelector.
29 *@param a_simple_sel the initial simple selector list
30 *of the current instance of #CRSelector.
31 *@return the newly built instance of #CRSelector, or
32 *NULL in case of failure.
33 */
34 CRSelector *
35 cr_selector_new (CRSimpleSel * a_simple_sel)
36 {
37 CRSelector *result = NULL;
39 result = g_try_malloc (sizeof (CRSelector));
40 if (!result) {
41 cr_utils_trace_info ("Out of memory");
42 return NULL;
43 }
44 memset (result, 0, sizeof (CRSelector));
45 result->simple_sel = a_simple_sel;
46 return result;
47 }
49 CRSelector *
50 cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
51 {
52 CRParser *parser = NULL;
54 g_return_val_if_fail (a_char_buf, NULL);
56 parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen (a_char_buf),
57 a_enc, FALSE);
58 g_return_val_if_fail (parser, NULL);
60 return NULL;
61 }
63 /**
64 *Appends a new instance of #CRSelector to the current selector list.
65 *@param a_this the current instance of #CRSelector.
66 *@param a_new the instance of #CRSelector to be appended.
67 *@return the new list.
68 */
69 CRSelector *
70 cr_selector_append (CRSelector * a_this, CRSelector * a_new)
71 {
72 CRSelector *cur = NULL;
74 if (!a_this) {
75 return a_new;
76 }
78 /*walk forward the list headed by a_this to get the list tail */
79 for (cur = a_this; cur && cur->next; cur = cur->next) ;
81 cur->next = a_new;
82 a_new->prev = cur;
84 return a_this;
85 }
87 /**
88 *Prepends an element to the #CRSelector list.
89 *@param a_this the current instance of #CRSelector list.
90 *@param a_new the instance of #CRSelector.
91 *@return the new list.
92 */
93 CRSelector *
94 cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
95 {
96 CRSelector *cur = NULL;
98 a_new->next = a_this;
99 a_this->prev = a_new;
101 for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
103 return cur;
104 }
106 /**
107 *append a simple selector to the current #CRSelector list.
108 *@param a_this the current instance of #CRSelector.
109 *@param a_simple_sel the simple selector to append.
110 *@return the new list or NULL in case of failure.
111 */
112 CRSelector *
113 cr_selector_append_simple_sel (CRSelector * a_this,
114 CRSimpleSel * a_simple_sel)
115 {
116 CRSelector *selector = NULL;
118 selector = cr_selector_new (a_simple_sel);
119 g_return_val_if_fail (selector, NULL);
121 return cr_selector_append (a_this, selector);
122 }
124 guchar *
125 cr_selector_to_string (CRSelector * a_this)
126 {
127 guchar *result = NULL;
128 GString *str_buf = NULL;
130 str_buf = g_string_new (NULL);
131 g_return_val_if_fail (str_buf, NULL);
133 if (a_this) {
134 CRSelector *cur = NULL;
136 for (cur = a_this; cur; cur = cur->next) {
137 if (cur->simple_sel) {
138 guchar *tmp_str = NULL;
140 tmp_str = cr_simple_sel_to_string
141 (cur->simple_sel);
143 if (tmp_str) {
144 if (cur->prev)
145 g_string_append (str_buf,
146 ", ");
148 g_string_append (str_buf, tmp_str);
150 g_free (tmp_str);
151 tmp_str = NULL;
152 }
153 }
154 }
155 }
157 if (str_buf) {
158 result = str_buf->str;
159 g_string_free (str_buf, FALSE);
160 str_buf = NULL;
161 }
163 return result;
164 }
166 /**
167 *Serializes the current instance of #CRSelector to a file.
168 *@param a_this the current instance of #CRSelector.
169 *@param a_fp the destination file.
170 */
171 void
172 cr_selector_dump (CRSelector * a_this, FILE * a_fp)
173 {
174 guchar *tmp_buf = NULL;
176 if (a_this) {
177 tmp_buf = cr_selector_to_string (a_this);
178 if (tmp_buf) {
179 fprintf (a_fp, "%s", tmp_buf);
180 g_free (tmp_buf);
181 tmp_buf = NULL;
182 }
183 }
184 }
186 /**
187 *Increments the ref count of the current instance
188 *of #CRSelector.
189 *@param a_this the current instance of #CRSelector.
190 */
191 void
192 cr_selector_ref (CRSelector * a_this)
193 {
194 g_return_if_fail (a_this);
196 a_this->ref_count++;
197 }
199 /**
200 *Decrements the ref count of the current instance of
201 *#CRSelector.
202 *If the ref count reaches zero, the current instance of
203 *#CRSelector is destroyed.
204 *@param a_this the current instance of #CRSelector.
205 *@return TRUE if this function destroyed the current instance
206 *of #CRSelector, FALSE otherwise.
207 */
208 gboolean
209 cr_selector_unref (CRSelector * a_this)
210 {
211 g_return_val_if_fail (a_this, FALSE);
213 if (a_this->ref_count) {
214 a_this->ref_count--;
215 }
217 if (a_this->ref_count == 0) {
218 cr_selector_destroy (a_this);
219 return TRUE;
220 }
222 return FALSE;
223 }
225 /**
226 *Destroys the selector list.
227 *@param a_this the current instance of #CRSelector.
228 */
229 void
230 cr_selector_destroy (CRSelector * a_this)
231 {
232 CRSelector *cur = NULL;
234 g_return_if_fail (a_this);
236 /*
237 *go and get the list tail. In the same time, free
238 *all the simple selectors contained in the list.
239 */
240 for (cur = a_this; cur && cur->next; cur = cur->next) {
241 if (cur->simple_sel) {
242 cr_simple_sel_destroy (cur->simple_sel);
243 cur->simple_sel = NULL;
244 }
245 }
247 if (cur) {
248 if (cur->simple_sel) {
249 cr_simple_sel_destroy (cur->simple_sel);
250 cur->simple_sel = NULL;
251 }
252 }
254 /*in case the list has only one element */
255 if (cur && !cur->prev) {
256 g_free (cur);
257 return;
258 }
260 /*walk backward the list and free each "next element" */
261 for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
262 if (cur->next) {
263 g_free (cur->next);
264 cur->next = NULL;
265 }
266 }
268 if (!cur)
269 return;
271 if (cur->next) {
272 g_free (cur->next);
273 cur->next = NULL;
274 }
276 g_free (cur);
277 }