• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2 
3 /* libcroco - Library for parsing and applying CSS
4  * Copyright (C) 2006-2019 Free Software Foundation, Inc.
5  *
6  * This file is not part of the GNU gettext program, but is used with
7  * GNU gettext.
8  *
9  * The original copyright notice is as follows:
10  */
11 
12 /*
13  * This file is part of The Croco Library
14  *
15  * Copyright (C) 2003-2004 Dodji Seketeli.  All Rights Reserved.
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of version 2.1 of the GNU Lesser General Public
19  * License as published by the Free Software Foundation.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29  * USA
30  */
31 
32 #include <config.h>
33 #include <stdio.h>
34 #include "cr-attr-sel.h"
35 
36 /**
37  * CRAttrSel:
38  *
39  * #CRAdditionalSel abstracts an attribute selector.
40  * Attributes selectors are described in the css2 spec [5.8].
41  * There are more generally used in the css2 selectors described in
42  * css2 spec [5] .
43  */
44 
45 /**
46  * cr_attr_sel_new:
47  * The constructor of #CRAttrSel.
48  * Returns the newly allocated instance
49  * of #CRAttrSel.
50  */
51 CRAttrSel *
cr_attr_sel_new(void)52 cr_attr_sel_new (void)
53 {
54         CRAttrSel *result = NULL;
55 
56         result = g_malloc0 (sizeof (CRAttrSel));
57 
58         return result;
59 }
60 
61 /**
62  * cr_attr_sel_append_attr_sel:
63  * @a_this: the this pointer of the current instance of  #CRAttrSel.
64  * @a_attr_sel: selector to append.
65  *
66  * Appends an attribute selector to the current list of
67  * attribute selectors represented by a_this.
68  * Returns CR_OK upon successfull completion, an error code otherwise.
69  */
70 enum CRStatus
cr_attr_sel_append_attr_sel(CRAttrSel * a_this,CRAttrSel * a_attr_sel)71 cr_attr_sel_append_attr_sel (CRAttrSel * a_this, CRAttrSel * a_attr_sel)
72 {
73         CRAttrSel *cur_sel = NULL;
74 
75         g_return_val_if_fail (a_this && a_attr_sel,
76                               CR_BAD_PARAM_ERROR);
77 
78         for (cur_sel = a_this;
79              cur_sel->next;
80              cur_sel = cur_sel->next) ;
81 
82         cur_sel->next = a_attr_sel;
83         a_attr_sel->prev = cur_sel;
84 
85         return CR_OK;
86 }
87 
88 /**
89  * cr_attr_sel_prepend_attr_sel:
90  *@a_this: the "this pointer" of the current instance *of #CRAttrSel.
91  *@a_attr_sel: the attribute selector to append.
92  *
93  *Prepends an attribute selector to the list of
94  *attributes selector represented by a_this.
95  *Returns CR_OK upon successfull completion, an error code otherwise.
96  */
97 enum CRStatus
cr_attr_sel_prepend_attr_sel(CRAttrSel * a_this,CRAttrSel * a_attr_sel)98 cr_attr_sel_prepend_attr_sel (CRAttrSel * a_this,
99                               CRAttrSel * a_attr_sel)
100 {
101         g_return_val_if_fail (a_this && a_attr_sel,
102                               CR_BAD_PARAM_ERROR);
103 
104         a_attr_sel->next = a_this;
105         a_this->prev = a_attr_sel;
106 
107         return CR_OK;
108 }
109 
110 /**
111  * cr_attr_sel_to_string:
112  * @a_this: the current instance of #CRAttrSel.
113  *
114  * Serializes an attribute selector into a string
115  * Returns the serialized attribute selector.
116  */
117 guchar *
cr_attr_sel_to_string(CRAttrSel const * a_this)118 cr_attr_sel_to_string (CRAttrSel const * a_this)
119 {
120         CRAttrSel const *cur = NULL;
121         guchar *result = NULL;
122         GString *str_buf = NULL;
123 
124         g_return_val_if_fail (a_this, NULL);
125 
126         str_buf = g_string_new (NULL);
127 
128         for (cur = a_this; cur; cur = cur->next) {
129                 if (cur->prev) {
130                         g_string_append_c (str_buf, ' ');
131                 }
132 
133                 if (cur->name) {
134                         guchar *name = NULL;
135 
136                         name = (guchar *) g_strndup (cur->name->stryng->str,
137                                           cur->name->stryng->len);
138                         if (name) {
139                                 g_string_append (str_buf, (const gchar *) name);
140                                 g_free (name);
141                                 name = NULL;
142                         }
143                 }
144 
145                 if (cur->value) {
146                         guchar *value = NULL;
147 
148                         value = (guchar *) g_strndup (cur->value->stryng->str,
149                                            cur->value->stryng->len);
150                         if (value) {
151                                 switch (cur->match_way) {
152                                 case SET:
153                                         break;
154 
155                                 case EQUALS:
156                                         g_string_append_c (str_buf, '=');
157                                         break;
158 
159                                 case INCLUDES:
160                                         g_string_append (str_buf, "~=");
161                                         break;
162 
163                                 case DASHMATCH:
164                                         g_string_append (str_buf, "|=");
165                                         break;
166 
167                                 default:
168                                         break;
169                                 }
170 
171                                 g_string_append_printf
172                                         (str_buf, "\"%s\"", value);
173 
174                                 g_free (value);
175                                 value = NULL;
176                         }
177                 }
178         }
179 
180         if (str_buf) {
181                 result = (guchar *) str_buf->str;
182                 g_string_free (str_buf, FALSE);
183         }
184 
185         return result;
186 }
187 
188 /**
189  * cr_attr_sel_dump:
190  * @a_this: the "this pointer" of the current instance of
191  * #CRAttrSel.
192  * @a_fp: the destination file.
193  *
194  * Dumps the current instance of #CRAttrSel to a file.
195  */
196 void
cr_attr_sel_dump(CRAttrSel const * a_this,FILE * a_fp)197 cr_attr_sel_dump (CRAttrSel const * a_this, FILE * a_fp)
198 {
199         guchar *tmp_str = NULL;
200 
201         g_return_if_fail (a_this);
202 
203         tmp_str = cr_attr_sel_to_string (a_this);
204 
205         if (tmp_str) {
206                 fprintf (a_fp, "%s", tmp_str);
207                 g_free (tmp_str);
208                 tmp_str = NULL;
209         }
210 }
211 
212 /**
213  *cr_attr_sel_destroy:
214  *@a_this: the "this pointer" of the current
215  *instance of #CRAttrSel.
216  *
217  *Destroys the current instance of #CRAttrSel.
218  *Frees all the fields if they are non null.
219  */
220 void
cr_attr_sel_destroy(CRAttrSel * a_this)221 cr_attr_sel_destroy (CRAttrSel * a_this)
222 {
223         g_return_if_fail (a_this);
224 
225         if (a_this->name) {
226                 cr_string_destroy (a_this->name);
227                 a_this->name = NULL;
228         }
229 
230         if (a_this->value) {
231                 cr_string_destroy (a_this->value);
232                 a_this->value = NULL;
233         }
234 
235         if (a_this->next) {
236                 cr_attr_sel_destroy (a_this->next);
237                 a_this->next = NULL;
238         }
239 
240         if (a_this) {
241                 g_free (a_this);
242                 a_this = NULL;
243         }
244 }
245 
246