1 /***************************************************************************
2 * CVSID: $Id$
3 *
4 * property.c : HalProperty methods
5 *
6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7 * Copyright (C) 2004 Novell, Inc.
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 **************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30
31 #include <string.h>
32 #include <glib.h>
33
34 #include "logger.h"
35 #include "property.h"
36
37 struct _HalProperty {
38 char *key;
39
40 int type;
41 union {
42 char *str_value;
43 dbus_int32_t int_value;
44 dbus_uint64_t uint64_value;
45 dbus_bool_t bool_value;
46 double double_value;
47 GSList *strlist_value;
48 } v;
49 gboolean readonly;
50 gboolean persistence;
51 gboolean callout;
52 };
53
54 void
hal_property_free(HalProperty * prop)55 hal_property_free (HalProperty *prop)
56 {
57
58 g_free (prop->key);
59
60 if (prop->type == HAL_PROPERTY_TYPE_STRING) {
61 g_free (prop->v.str_value);
62 } else if (prop->type == HAL_PROPERTY_TYPE_STRLIST) {
63 GSList *i;
64 for (i = prop->v.strlist_value; i != NULL; i = g_slist_next (i)) {
65 g_free (i->data);
66 }
67 g_slist_free (prop->v.strlist_value);
68 }
69
70 g_free (prop);
71 }
72
73 HalProperty *
hal_property_new_string(const char * key,const char * value)74 hal_property_new_string (const char *key, const char *value)
75 {
76 HalProperty *prop;
77 char *endchar;
78 gboolean validated = TRUE;
79
80 prop = g_new0 (HalProperty, 1);
81
82 prop->type = HAL_PROPERTY_TYPE_STRING;
83 prop->key = g_strdup (key);
84 prop->v.str_value = g_strdup (value != NULL ? value : "");
85
86 while (!g_utf8_validate (prop->v.str_value, -1,
87 (const char **) &endchar)) {
88 validated = FALSE;
89 *endchar = '?';
90 }
91
92 if (!validated) {
93 HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'",
94 key, prop->v.str_value));
95 }
96
97 return prop;
98 }
99
100 HalProperty *
hal_property_new_int(const char * key,dbus_int32_t value)101 hal_property_new_int (const char *key, dbus_int32_t value)
102 {
103 HalProperty *prop;
104
105 prop = g_new0 (HalProperty, 1);
106
107 prop->type = HAL_PROPERTY_TYPE_INT32;
108 prop->key = g_strdup (key);
109 prop->v.int_value = value;
110
111 return prop;
112 }
113
114 HalProperty *
hal_property_new_uint64(const char * key,dbus_uint64_t value)115 hal_property_new_uint64 (const char *key, dbus_uint64_t value)
116 {
117 HalProperty *prop;
118
119 prop = g_new0 (HalProperty, 1);
120
121 prop->type = HAL_PROPERTY_TYPE_UINT64;
122 prop->key = g_strdup (key);
123 prop->v.uint64_value = value;
124
125 return prop;
126 }
127
128 HalProperty *
hal_property_new_bool(const char * key,dbus_bool_t value)129 hal_property_new_bool (const char *key, dbus_bool_t value)
130 {
131 HalProperty *prop;
132
133 prop = g_new0 (HalProperty, 1);
134
135 prop->type = HAL_PROPERTY_TYPE_BOOLEAN;
136 prop->key = g_strdup (key);
137 prop->v.bool_value = value;
138
139 return prop;
140 }
141
142 HalProperty *
hal_property_new_double(const char * key,double value)143 hal_property_new_double (const char *key, double value)
144 {
145 HalProperty *prop;
146
147 prop = g_new0 (HalProperty, 1);
148
149 prop->type = HAL_PROPERTY_TYPE_DOUBLE;
150 prop->key = g_strdup (key);
151 prop->v.double_value = value;
152
153 return prop;
154 }
155
156 const char *
hal_property_get_key(HalProperty * prop)157 hal_property_get_key (HalProperty *prop)
158 {
159 g_return_val_if_fail (prop != NULL, NULL);
160
161 return prop->key;
162 }
163
164 int
hal_property_get_type(HalProperty * prop)165 hal_property_get_type (HalProperty *prop)
166 {
167 g_return_val_if_fail (prop != NULL, HAL_PROPERTY_TYPE_INVALID);
168
169 return prop->type;
170 }
171
172 const char *
hal_property_get_string(HalProperty * prop)173 hal_property_get_string (HalProperty *prop)
174 {
175 g_return_val_if_fail (prop != NULL, NULL);
176 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING, NULL);
177
178 return prop->v.str_value;
179 }
180
181 dbus_int32_t
hal_property_get_int(HalProperty * prop)182 hal_property_get_int (HalProperty *prop)
183 {
184 g_return_val_if_fail (prop != NULL, -1);
185 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32, -1);
186
187 return prop->v.int_value;
188 }
189
190 dbus_uint64_t
hal_property_get_uint64(HalProperty * prop)191 hal_property_get_uint64 (HalProperty *prop)
192 {
193 g_return_val_if_fail (prop != NULL, -1);
194 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64, -1);
195
196 return prop->v.uint64_value;
197 }
198
199 dbus_bool_t
hal_property_get_bool(HalProperty * prop)200 hal_property_get_bool (HalProperty *prop)
201 {
202 g_return_val_if_fail (prop != NULL, FALSE);
203 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN, FALSE);
204
205 return prop->v.bool_value;
206 }
207
208 char *
hal_property_to_string(HalProperty * prop)209 hal_property_to_string (HalProperty *prop)
210 {
211 g_return_val_if_fail (prop != NULL, NULL);
212
213 switch (prop->type) {
214 case HAL_PROPERTY_TYPE_STRING:
215 return g_strdup (prop->v.str_value);
216 case HAL_PROPERTY_TYPE_INT32:
217 return g_strdup_printf ("%d", prop->v.int_value);
218 case HAL_PROPERTY_TYPE_UINT64:
219 return g_strdup_printf ("%llu", (long long unsigned int) prop->v.uint64_value);
220 case HAL_PROPERTY_TYPE_BOOLEAN:
221 /* FIXME: Maybe use 1 and 0 here instead? */
222 return g_strdup (prop->v.bool_value ? "true" : "false");
223 case HAL_PROPERTY_TYPE_DOUBLE:
224 return g_strdup_printf ("%f", prop->v.double_value);
225 case HAL_PROPERTY_TYPE_STRLIST:
226 {
227 GSList *iter;
228 guint i;
229 char buf[256];
230
231 i = 0;
232 buf[0] = '\0';
233 for (iter = hal_property_get_strlist (prop);
234 iter != NULL && i < sizeof(buf);
235 iter = g_slist_next (iter)) {
236 guint len;
237 const char *str;
238
239 str = (const char *) iter->data;
240 len = strlen (str);
241 strncpy (buf + i, str, sizeof(buf) - i);
242 i += len;
243
244 if (g_slist_next (iter) != NULL && i < sizeof(buf)) {
245 buf[i] = '\t';
246 i++;
247 }
248 }
249 return g_strdup (buf);
250 }
251
252 default:
253 return NULL;
254 }
255 }
256
257 double
hal_property_get_double(HalProperty * prop)258 hal_property_get_double (HalProperty *prop)
259 {
260 g_return_val_if_fail (prop != NULL, -1.0);
261 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE, -1.0);
262
263 return prop->v.double_value;
264 }
265
266 void
hal_property_set_string(HalProperty * prop,const char * value)267 hal_property_set_string (HalProperty *prop, const char *value)
268 {
269 char *endchar;
270 gboolean validated = TRUE;
271
272 g_return_if_fail (prop != NULL);
273 g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING ||
274 prop->type == HAL_PROPERTY_TYPE_INVALID);
275
276 prop->type = HAL_PROPERTY_TYPE_STRING;
277 if (prop->v.str_value != NULL)
278 g_free (prop->v.str_value);
279 prop->v.str_value = g_strdup (value);
280
281 while (!g_utf8_validate (prop->v.str_value, -1,
282 (const char **) &endchar)) {
283 validated = FALSE;
284 *endchar = '?';
285 }
286
287 if (!validated) {
288 HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'",
289 prop->key, value));
290 }
291 }
292
293 void
hal_property_set_int(HalProperty * prop,dbus_int32_t value)294 hal_property_set_int (HalProperty *prop, dbus_int32_t value)
295 {
296 g_return_if_fail (prop != NULL);
297 g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32 ||
298 prop->type == HAL_PROPERTY_TYPE_INVALID);
299
300 prop->type = HAL_PROPERTY_TYPE_INT32;
301 prop->v.int_value = value;
302 }
303
304 void
hal_property_set_uint64(HalProperty * prop,dbus_uint64_t value)305 hal_property_set_uint64 (HalProperty *prop, dbus_uint64_t value)
306 {
307 g_return_if_fail (prop != NULL);
308 g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64 ||
309 prop->type == HAL_PROPERTY_TYPE_INVALID);
310
311 prop->type = HAL_PROPERTY_TYPE_UINT64;
312 prop->v.uint64_value = value;
313 }
314
315 void
hal_property_set_bool(HalProperty * prop,dbus_bool_t value)316 hal_property_set_bool (HalProperty *prop, dbus_bool_t value)
317 {
318 g_return_if_fail (prop != NULL);
319 g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN ||
320 prop->type == HAL_PROPERTY_TYPE_INVALID);
321
322 prop->type = HAL_PROPERTY_TYPE_BOOLEAN;
323 prop->v.bool_value = value;
324 }
325
326 void
hal_property_set_double(HalProperty * prop,double value)327 hal_property_set_double (HalProperty *prop, double value)
328 {
329 g_return_if_fail (prop != NULL);
330 g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE ||
331 prop->type == HAL_PROPERTY_TYPE_INVALID);
332
333 prop->type = HAL_PROPERTY_TYPE_DOUBLE;
334 prop->v.double_value = value;
335 }
336
337 void
hal_property_set_attribute(HalProperty * prop,enum PropertyAttribute attr,gboolean val)338 hal_property_set_attribute (HalProperty *prop,
339 enum PropertyAttribute attr,
340 gboolean val)
341 {
342 g_return_if_fail (prop != NULL);
343
344 switch (attr) {
345 case READONLY:
346 prop->readonly = val;
347 break;
348 case PERSISTENCE:
349 prop->persistence = val;
350 break;
351 case CALLOUT:
352 prop->callout = val;
353 break;
354 }
355 }
356
357 gboolean
hal_property_get_attribute(HalProperty * prop,enum PropertyAttribute attr)358 hal_property_get_attribute (HalProperty *prop,
359 enum PropertyAttribute attr)
360 {
361 g_return_val_if_fail (prop != NULL, -1);
362
363 switch (attr) {
364 case READONLY:
365 return prop->readonly;
366 case PERSISTENCE:
367 return prop->persistence;
368 case CALLOUT:
369 return prop->callout;
370 default:
371 return -1;
372 }
373 }
374
375 HalProperty *
hal_property_new_strlist(const char * key)376 hal_property_new_strlist (const char *key)
377 {
378 HalProperty *prop;
379
380 prop = g_new0 (HalProperty, 1);
381
382 prop->type = HAL_PROPERTY_TYPE_STRLIST;
383 prop->key = g_strdup (key);
384 prop->v.strlist_value = NULL;
385
386 return prop;
387 }
388
389 GSList *
hal_property_get_strlist(HalProperty * prop)390 hal_property_get_strlist (HalProperty *prop)
391 {
392 g_return_val_if_fail (prop != NULL, NULL);
393 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, NULL);
394
395 return prop->v.strlist_value;
396 }
397
398 gboolean
hal_property_strlist_append(HalProperty * prop,const char * value)399 hal_property_strlist_append (HalProperty *prop, const char *value)
400 {
401 g_return_val_if_fail (prop != NULL, FALSE);
402 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
403
404 prop->v.strlist_value = g_slist_append (prop->v.strlist_value, g_strdup (value));
405
406 return TRUE;
407 }
408
409 gboolean
hal_property_strlist_prepend(HalProperty * prop,const char * value)410 hal_property_strlist_prepend (HalProperty *prop, const char *value)
411 {
412 g_return_val_if_fail (prop != NULL, FALSE);
413 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
414
415 prop->v.strlist_value = g_slist_prepend (prop->v.strlist_value, g_strdup (value));
416
417 return TRUE;
418 }
419
420 gboolean
hal_property_strlist_remove_elem(HalProperty * prop,guint index)421 hal_property_strlist_remove_elem (HalProperty *prop, guint index)
422 {
423 GSList *elem;
424
425 g_return_val_if_fail (prop != NULL, FALSE);
426 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
427
428 if (prop->v.strlist_value == NULL)
429 return FALSE;
430
431 elem = g_slist_nth (prop->v.strlist_value, index);
432 if (elem == NULL)
433 return FALSE;
434
435 g_free (elem->data);
436 prop->v.strlist_value = g_slist_delete_link (prop->v.strlist_value, elem);
437 return TRUE;
438 }
439
440
441 gboolean
hal_property_strlist_add(HalProperty * prop,const char * value)442 hal_property_strlist_add (HalProperty *prop, const char *value)
443 {
444 GSList *elem;
445
446 g_return_val_if_fail (prop != NULL, FALSE);
447 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
448
449 for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) {
450 if (strcmp (elem->data, value) == 0) {
451 return FALSE;
452 }
453 }
454
455 return hal_property_strlist_append (prop, value);
456 }
457
458 gboolean
hal_property_strlist_remove(HalProperty * prop,const char * value)459 hal_property_strlist_remove (HalProperty *prop, const char *value)
460 {
461 guint i;
462 GSList *elem;
463
464 g_return_val_if_fail (prop != NULL, FALSE);
465 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
466
467 for (elem = prop->v.strlist_value, i = 0; elem != NULL; elem = g_slist_next (elem), i++) {
468 if (strcmp (elem->data, value) == 0) {
469 return hal_property_strlist_remove_elem (prop, i);
470 }
471 }
472
473 return FALSE;
474 }
475
476 gboolean
hal_property_strlist_clear(HalProperty * prop)477 hal_property_strlist_clear (HalProperty *prop)
478 {
479 GSList *elem;
480
481 g_return_val_if_fail (prop != NULL, FALSE);
482 g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
483
484 for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) {
485 g_free (elem->data);
486 }
487 g_slist_free (prop->v.strlist_value);
488
489 return FALSE;
490 }
491