/*************************************************************************** * CVSID: $Id$ * * property.c : HalProperty methods * * Copyright (C) 2003 David Zeuthen, * Copyright (C) 2004 Novell, Inc. * * Licensed under the Academic Free License version 2.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * **************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "logger.h" #include "property.h" struct _HalProperty { char *key; int type; union { char *str_value; dbus_int32_t int_value; dbus_uint64_t uint64_value; dbus_bool_t bool_value; double double_value; GSList *strlist_value; } v; gboolean readonly; gboolean persistence; gboolean callout; }; void hal_property_free (HalProperty *prop) { g_free (prop->key); if (prop->type == HAL_PROPERTY_TYPE_STRING) { g_free (prop->v.str_value); } else if (prop->type == HAL_PROPERTY_TYPE_STRLIST) { GSList *i; for (i = prop->v.strlist_value; i != NULL; i = g_slist_next (i)) { g_free (i->data); } g_slist_free (prop->v.strlist_value); } g_free (prop); } HalProperty * hal_property_new_string (const char *key, const char *value) { HalProperty *prop; char *endchar; gboolean validated = TRUE; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_STRING; prop->key = g_strdup (key); prop->v.str_value = g_strdup (value != NULL ? value : ""); while (!g_utf8_validate (prop->v.str_value, -1, (const char **) &endchar)) { validated = FALSE; *endchar = '?'; } if (!validated) { HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'", key, prop->v.str_value)); } return prop; } HalProperty * hal_property_new_int (const char *key, dbus_int32_t value) { HalProperty *prop; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_INT32; prop->key = g_strdup (key); prop->v.int_value = value; return prop; } HalProperty * hal_property_new_uint64 (const char *key, dbus_uint64_t value) { HalProperty *prop; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_UINT64; prop->key = g_strdup (key); prop->v.uint64_value = value; return prop; } HalProperty * hal_property_new_bool (const char *key, dbus_bool_t value) { HalProperty *prop; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_BOOLEAN; prop->key = g_strdup (key); prop->v.bool_value = value; return prop; } HalProperty * hal_property_new_double (const char *key, double value) { HalProperty *prop; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_DOUBLE; prop->key = g_strdup (key); prop->v.double_value = value; return prop; } const char * hal_property_get_key (HalProperty *prop) { g_return_val_if_fail (prop != NULL, NULL); return prop->key; } int hal_property_get_type (HalProperty *prop) { g_return_val_if_fail (prop != NULL, HAL_PROPERTY_TYPE_INVALID); return prop->type; } const char * hal_property_get_string (HalProperty *prop) { g_return_val_if_fail (prop != NULL, NULL); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING, NULL); return prop->v.str_value; } dbus_int32_t hal_property_get_int (HalProperty *prop) { g_return_val_if_fail (prop != NULL, -1); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32, -1); return prop->v.int_value; } dbus_uint64_t hal_property_get_uint64 (HalProperty *prop) { g_return_val_if_fail (prop != NULL, -1); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64, -1); return prop->v.uint64_value; } dbus_bool_t hal_property_get_bool (HalProperty *prop) { g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN, FALSE); return prop->v.bool_value; } char * hal_property_to_string (HalProperty *prop) { g_return_val_if_fail (prop != NULL, NULL); switch (prop->type) { case HAL_PROPERTY_TYPE_STRING: return g_strdup (prop->v.str_value); case HAL_PROPERTY_TYPE_INT32: return g_strdup_printf ("%d", prop->v.int_value); case HAL_PROPERTY_TYPE_UINT64: return g_strdup_printf ("%llu", (long long unsigned int) prop->v.uint64_value); case HAL_PROPERTY_TYPE_BOOLEAN: /* FIXME: Maybe use 1 and 0 here instead? */ return g_strdup (prop->v.bool_value ? "true" : "false"); case HAL_PROPERTY_TYPE_DOUBLE: return g_strdup_printf ("%f", prop->v.double_value); case HAL_PROPERTY_TYPE_STRLIST: { GSList *iter; guint i; char buf[256]; i = 0; buf[0] = '\0'; for (iter = hal_property_get_strlist (prop); iter != NULL && i < sizeof(buf); iter = g_slist_next (iter)) { guint len; const char *str; str = (const char *) iter->data; len = strlen (str); strncpy (buf + i, str, sizeof(buf) - i); i += len; if (g_slist_next (iter) != NULL && i < sizeof(buf)) { buf[i] = '\t'; i++; } } return g_strdup (buf); } default: return NULL; } } double hal_property_get_double (HalProperty *prop) { g_return_val_if_fail (prop != NULL, -1.0); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE, -1.0); return prop->v.double_value; } void hal_property_set_string (HalProperty *prop, const char *value) { char *endchar; gboolean validated = TRUE; g_return_if_fail (prop != NULL); g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING || prop->type == HAL_PROPERTY_TYPE_INVALID); prop->type = HAL_PROPERTY_TYPE_STRING; if (prop->v.str_value != NULL) g_free (prop->v.str_value); prop->v.str_value = g_strdup (value); while (!g_utf8_validate (prop->v.str_value, -1, (const char **) &endchar)) { validated = FALSE; *endchar = '?'; } if (!validated) { HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'", prop->key, value)); } } void hal_property_set_int (HalProperty *prop, dbus_int32_t value) { g_return_if_fail (prop != NULL); g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32 || prop->type == HAL_PROPERTY_TYPE_INVALID); prop->type = HAL_PROPERTY_TYPE_INT32; prop->v.int_value = value; } void hal_property_set_uint64 (HalProperty *prop, dbus_uint64_t value) { g_return_if_fail (prop != NULL); g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64 || prop->type == HAL_PROPERTY_TYPE_INVALID); prop->type = HAL_PROPERTY_TYPE_UINT64; prop->v.uint64_value = value; } void hal_property_set_bool (HalProperty *prop, dbus_bool_t value) { g_return_if_fail (prop != NULL); g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN || prop->type == HAL_PROPERTY_TYPE_INVALID); prop->type = HAL_PROPERTY_TYPE_BOOLEAN; prop->v.bool_value = value; } void hal_property_set_double (HalProperty *prop, double value) { g_return_if_fail (prop != NULL); g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE || prop->type == HAL_PROPERTY_TYPE_INVALID); prop->type = HAL_PROPERTY_TYPE_DOUBLE; prop->v.double_value = value; } void hal_property_set_attribute (HalProperty *prop, enum PropertyAttribute attr, gboolean val) { g_return_if_fail (prop != NULL); switch (attr) { case READONLY: prop->readonly = val; break; case PERSISTENCE: prop->persistence = val; break; case CALLOUT: prop->callout = val; break; } } gboolean hal_property_get_attribute (HalProperty *prop, enum PropertyAttribute attr) { g_return_val_if_fail (prop != NULL, -1); switch (attr) { case READONLY: return prop->readonly; case PERSISTENCE: return prop->persistence; case CALLOUT: return prop->callout; default: return -1; } } HalProperty * hal_property_new_strlist (const char *key) { HalProperty *prop; prop = g_new0 (HalProperty, 1); prop->type = HAL_PROPERTY_TYPE_STRLIST; prop->key = g_strdup (key); prop->v.strlist_value = NULL; return prop; } GSList * hal_property_get_strlist (HalProperty *prop) { g_return_val_if_fail (prop != NULL, NULL); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, NULL); return prop->v.strlist_value; } gboolean hal_property_strlist_append (HalProperty *prop, const char *value) { g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); prop->v.strlist_value = g_slist_append (prop->v.strlist_value, g_strdup (value)); return TRUE; } gboolean hal_property_strlist_prepend (HalProperty *prop, const char *value) { g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); prop->v.strlist_value = g_slist_prepend (prop->v.strlist_value, g_strdup (value)); return TRUE; } gboolean hal_property_strlist_remove_elem (HalProperty *prop, guint index) { GSList *elem; g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); if (prop->v.strlist_value == NULL) return FALSE; elem = g_slist_nth (prop->v.strlist_value, index); if (elem == NULL) return FALSE; g_free (elem->data); prop->v.strlist_value = g_slist_delete_link (prop->v.strlist_value, elem); return TRUE; } gboolean hal_property_strlist_add (HalProperty *prop, const char *value) { GSList *elem; g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) { if (strcmp (elem->data, value) == 0) { return FALSE; } } return hal_property_strlist_append (prop, value); } gboolean hal_property_strlist_remove (HalProperty *prop, const char *value) { guint i; GSList *elem; g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); for (elem = prop->v.strlist_value, i = 0; elem != NULL; elem = g_slist_next (elem), i++) { if (strcmp (elem->data, value) == 0) { return hal_property_strlist_remove_elem (prop, i); } } return FALSE; } gboolean hal_property_strlist_clear (HalProperty *prop) { GSList *elem; g_return_val_if_fail (prop != NULL, FALSE); g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE); for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) { g_free (elem->data); } g_slist_free (prop->v.strlist_value); return FALSE; }