]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssstringvalue.c
cssvalue: Don't crash when printing NULL strings
[~andy/gtk] / gtk / gtkcssstringvalue.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gtkcssstringvalueprivate.h"
21
22 #include <string.h>
23
24 struct _GtkCssValue {
25   GTK_CSS_VALUE_BASE
26   char *string;
27 };
28
29 static void
30 gtk_css_value_string_free (GtkCssValue *value)
31 {
32   g_free (value->string);
33   g_slice_free (GtkCssValue, value);
34 }
35
36 static GtkCssValue *
37 gtk_css_value_string_compute (GtkCssValue        *value,
38                               guint               property_id,
39                               GtkStyleContext    *context,
40                               GtkCssDependencies *dependencies)
41 {
42   return _gtk_css_value_ref (value);
43 }
44
45 static gboolean
46 gtk_css_value_string_equal (const GtkCssValue *value1,
47                             const GtkCssValue *value2)
48 {
49   return g_strcmp0 (value1->string, value2->string) == 0;
50 }
51
52 static GtkCssValue *
53 gtk_css_value_string_transition (GtkCssValue *start,
54                                  GtkCssValue *end,
55                                  guint        property_id,
56                                  double       progress)
57 {
58   return NULL;
59 }
60
61 static void
62 gtk_css_value_string_print (const GtkCssValue *value,
63                             GString           *str)
64 {
65   char *string = value->string;
66   gsize len;
67
68   if (string == NULL)
69     {
70       g_string_append (str, "none");
71       return;
72     }
73
74   g_string_append_c (str, '"');
75
76   do {
77     len = strcspn (string, "\"\n\r\f");
78     g_string_append_len (str, string, len);
79     string += len;
80     switch (*string)
81       {
82       case '\0':
83         break;
84       case '\n':
85         g_string_append (str, "\\A ");
86         break;
87       case '\r':
88         g_string_append (str, "\\D ");
89         break;
90       case '\f':
91         g_string_append (str, "\\C ");
92         break;
93       case '\"':
94         g_string_append (str, "\\\"");
95         break;
96       case '\\':
97         g_string_append (str, "\\\\");
98         break;
99       default:
100         g_assert_not_reached ();
101         break;
102       }
103   } while (*string);
104
105   g_string_append_c (str, '"');
106 }
107
108 static void
109 gtk_css_value_ident_print (const GtkCssValue *value,
110                             GString           *str)
111 {
112   char *string = value->string;
113   gsize len;
114
115   do {
116     len = strcspn (string, "\"\n\r\f");
117     g_string_append_len (str, string, len);
118     string += len;
119     switch (*string)
120       {
121       case '\0':
122         break;
123       case '\n':
124         g_string_append (str, "\\A ");
125         break;
126       case '\r':
127         g_string_append (str, "\\D ");
128         break;
129       case '\f':
130         g_string_append (str, "\\C ");
131         break;
132       case '\"':
133         g_string_append (str, "\\\"");
134         break;
135       case '\'':
136         g_string_append (str, "\\'");
137         break;
138       case '\\':
139         g_string_append (str, "\\\\");
140         break;
141       default:
142         g_assert_not_reached ();
143         break;
144       }
145   } while (*string);
146 }
147
148 static const GtkCssValueClass GTK_CSS_VALUE_STRING = {
149   gtk_css_value_string_free,
150   gtk_css_value_string_compute,
151   gtk_css_value_string_equal,
152   gtk_css_value_string_transition,
153   gtk_css_value_string_print
154 };
155
156 static const GtkCssValueClass GTK_CSS_VALUE_IDENT = {
157   gtk_css_value_string_free,
158   gtk_css_value_string_compute,
159   gtk_css_value_string_equal,
160   gtk_css_value_string_transition,
161   gtk_css_value_ident_print
162 };
163
164 GtkCssValue *
165 _gtk_css_string_value_new (const char *string)
166 {
167   return _gtk_css_string_value_new_take (g_strdup (string));
168 }
169
170 GtkCssValue *
171 _gtk_css_string_value_new_take (char *string)
172 {
173   GtkCssValue *result;
174
175   result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_STRING);
176   result->string = string;
177
178   return result;
179 }
180
181 GtkCssValue *
182 _gtk_css_string_value_parse (GtkCssParser *parser)
183 {
184   char *s;
185
186   g_return_val_if_fail (parser != NULL, NULL);
187
188   s = _gtk_css_parser_read_string (parser);
189   if (s == NULL)
190     return NULL;
191   
192   return _gtk_css_string_value_new_take (s);
193 }
194
195 const char *
196 _gtk_css_string_value_get (const GtkCssValue *value)
197 {
198   g_return_val_if_fail (value != NULL, NULL);
199   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_STRING, NULL);
200
201   return value->string;
202 }
203
204 GtkCssValue *
205 _gtk_css_ident_value_new (const char *ident)
206 {
207   return _gtk_css_ident_value_new_take (g_strdup (ident));
208 }
209
210 GtkCssValue *
211 _gtk_css_ident_value_new_take (char *ident)
212 {
213   GtkCssValue *result;
214
215   result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_IDENT);
216   result->string = ident;
217
218   return result;
219 }
220
221 GtkCssValue *
222 _gtk_css_ident_value_try_parse (GtkCssParser *parser)
223 {
224   char *ident;
225
226   g_return_val_if_fail (parser != NULL, NULL);
227
228   ident = _gtk_css_parser_try_ident (parser, TRUE);
229   if (ident == NULL)
230     return NULL;
231   
232   return _gtk_css_ident_value_new_take (ident);
233 }
234
235 const char *
236 _gtk_css_ident_value_get (const GtkCssValue *value)
237 {
238   g_return_val_if_fail (value != NULL, NULL);
239   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_IDENT, NULL);
240
241   return value->string;
242 }
243