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 = (CRSelector *)g_try_malloc (sizeof (CRSelector));
38 if (!result) {
39 cr_utils_trace_info ("Out of memory");
40 return NULL;
41 }
42 memset (result, 0, sizeof (CRSelector));
43 result->simple_sel = a_simple_sel;
44 return result;
45 }
47 CRSelector *
48 cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
49 {
50 CRParser *parser = NULL;
52 g_return_val_if_fail (a_char_buf, NULL);
54 parser = cr_parser_new_from_buf ((guchar*)a_char_buf,
55 strlen ((char *)a_char_buf),
56 a_enc, FALSE);
57 g_return_val_if_fail (parser, NULL);
59 return NULL;
60 }
62 /**
63 *Appends a new instance of #CRSelector to the current selector list.
64 *@param a_this the current instance of #CRSelector.
65 *@param a_new the instance of #CRSelector to be appended.
66 *@return the new list.
67 */
68 CRSelector *
69 cr_selector_append (CRSelector * a_this, CRSelector * a_new)
70 {
71 CRSelector *cur = NULL;
73 if (!a_this) {
74 return a_new;
75 }
77 /*walk forward the list headed by a_this to get the list tail */
78 for (cur = a_this; cur && cur->next; cur = cur->next) ;
80 cur->next = a_new;
81 a_new->prev = cur;
83 return a_this;
84 }
86 /**
87 *Prepends an element to the #CRSelector list.
88 *@param a_this the current instance of #CRSelector list.
89 *@param a_new the instance of #CRSelector.
90 *@return the new list.
91 */
92 CRSelector *
93 cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
94 {
95 CRSelector *cur = NULL;
97 a_new->next = a_this;
98 a_this->prev = a_new;
100 for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
102 return cur;
103 }
105 /**
106 *append a simple selector to the current #CRSelector list.
107 *@param a_this the current instance of #CRSelector.
108 *@param a_simple_sel the simple selector to append.
109 *@return the new list or NULL in case of failure.
110 */
111 CRSelector *
112 cr_selector_append_simple_sel (CRSelector * a_this,
113 CRSimpleSel * a_simple_sel)
114 {
115 CRSelector *selector = NULL;
117 selector = cr_selector_new (a_simple_sel);
118 g_return_val_if_fail (selector, NULL);
120 return cr_selector_append (a_this, selector);
121 }
123 guchar *
124 cr_selector_to_string (CRSelector * a_this)
125 {
126 guchar *result = NULL;
128 GString *str_buf = (GString *)g_string_new (NULL);
129 g_return_val_if_fail (str_buf, NULL);
131 if (a_this) {
132 CRSelector *cur = NULL;
134 for (cur = a_this; cur; cur = cur->next) {
135 if (cur->simple_sel) {
136 guchar *tmp_str = NULL;
138 tmp_str = cr_simple_sel_to_string
139 (cur->simple_sel);
141 if (tmp_str) {
142 if (cur->prev)
143 g_string_append (str_buf,
144 ", ");
146 g_string_append (str_buf, (gchar *)tmp_str);
148 g_free (tmp_str);
149 tmp_str = NULL;
150 }
151 }
152 }
153 }
155 if (str_buf) {
156 result = (guchar *)str_buf->str;
157 g_string_free (str_buf, FALSE);
158 str_buf = NULL;
159 }
161 return result;
162 }
164 /**
165 *Serializes the current instance of #CRSelector to a file.
166 *@param a_this the current instance of #CRSelector.
167 *@param a_fp the destination file.
168 */
169 void
170 cr_selector_dump (CRSelector * a_this, FILE * a_fp)
171 {
172 guchar *tmp_buf = NULL;
174 if (a_this) {
175 tmp_buf = cr_selector_to_string (a_this);
176 if (tmp_buf) {
177 fprintf (a_fp, "%s", tmp_buf);
178 g_free (tmp_buf);
179 tmp_buf = NULL;
180 }
181 }
182 }
184 /**
185 *Increments the ref count of the current instance
186 *of #CRSelector.
187 *@param a_this the current instance of #CRSelector.
188 */
189 void
190 cr_selector_ref (CRSelector * a_this)
191 {
192 g_return_if_fail (a_this);
194 a_this->ref_count++;
195 }
197 /**
198 *Decrements the ref count of the current instance of
199 *#CRSelector.
200 *If the ref count reaches zero, the current instance of
201 *#CRSelector is destroyed.
202 *@param a_this the current instance of #CRSelector.
203 *@return TRUE if this function destroyed the current instance
204 *of #CRSelector, FALSE otherwise.
205 */
206 gboolean
207 cr_selector_unref (CRSelector * a_this)
208 {
209 g_return_val_if_fail (a_this, FALSE);
211 if (a_this->ref_count) {
212 a_this->ref_count--;
213 }
215 if (a_this->ref_count == 0) {
216 cr_selector_destroy (a_this);
217 return TRUE;
218 }
220 return FALSE;
221 }
223 /**
224 *Destroys the selector list.
225 *@param a_this the current instance of #CRSelector.
226 */
227 void
228 cr_selector_destroy (CRSelector * a_this)
229 {
230 CRSelector *cur = NULL;
232 g_return_if_fail (a_this);
234 /*
235 *go and get the list tail. In the same time, free
236 *all the simple selectors contained in the list.
237 */
238 for (cur = a_this; cur && cur->next; cur = cur->next) {
239 if (cur->simple_sel) {
240 cr_simple_sel_destroy (cur->simple_sel);
241 cur->simple_sel = NULL;
242 }
243 }
245 if (cur) {
246 if (cur->simple_sel) {
247 cr_simple_sel_destroy (cur->simple_sel);
248 cur->simple_sel = NULL;
249 }
250 }
252 /*in case the list has only one element */
253 if (cur && !cur->prev) {
254 g_free (cur);
255 return;
256 }
258 /*walk backward the list and free each "next element" */
259 for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
260 if (cur->next) {
261 g_free (cur->next);
262 cur->next = NULL;
263 }
264 }
266 if (!cur)
267 return;
269 if (cur->next) {
270 g_free (cur->next);
271 cur->next = NULL;
272 }
274 g_free (cur);
275 }