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 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 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 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 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 * 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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