/* * Copyright (C) 2005 Kouji TAKAO * * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "gpass/attribute-list.h" /*********************************************************** * * GPassAttributeListCursor * ***********************************************************/ static void attribute_list_cursor_instance_init(GTypeInstance *instance, gpointer g_class) { GPassAttributeListCursor *self = GPASS_ATTRIBUTE_LIST_CURSOR(instance); self->current = NULL; } enum { CURSOR_PROP_0, CURSOR_PROP_LIST, CURSOR_PROP_ATTRIBUTE, }; static void attribute_list_cursor_instance_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GPassAttributeListCursor *self = GPASS_ATTRIBUTE_LIST_CURSOR(object); switch (prop_id) { case CURSOR_PROP_LIST: self->current = g_value_get_pointer(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void attribute_list_cursor_instance_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GPassAttributeListCursor *self = GPASS_ATTRIBUTE_LIST_CURSOR(object); switch (prop_id) { case CURSOR_PROP_ATTRIBUTE: if (self->current == NULL) { g_value_set_object(value, NULL); } else { g_value_set_object(value, self->current->data); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void attribute_list_cursor_class_init(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); gobject_class->set_property = attribute_list_cursor_instance_set_property; gobject_class->get_property = attribute_list_cursor_instance_get_property; g_object_class_install_property (gobject_class, CURSOR_PROP_LIST, g_param_spec_pointer("list", _("List"), _("The pointer of attribute GList"), G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, CURSOR_PROP_ATTRIBUTE, g_param_spec_object("attribute", _("Attribute"), _("The object of GPassAttribute"), GPASS_TYPE_ATTRIBUTE, G_PARAM_READABLE)); } GType gpass_attribute_list_cursor_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassAttributeListCursorClass), NULL, NULL, attribute_list_cursor_class_init, NULL, NULL, sizeof(GPassAttributeListCursor), 0, attribute_list_cursor_instance_init }; type = g_type_register_static(G_TYPE_OBJECT, "GPassAttributeListCursor", &info, 0); } return type; } GError * gpass_attribute_list_cursor_next(GPassAttributeListCursor *self) { if (self->current == NULL) { GError *error = NULL; g_set_error(&error, 0, 0, _("end of cursor")); return error; } self->current = g_list_next(self->current); return NULL; } gboolean gpass_attribute_list_cursor_is_done(GPassAttributeListCursor *self) { return self->current == NULL; } /*********************************************************** * * GPassAttributeList * ***********************************************************/ static GObjectClass *parent_list_class = NULL; static void attribute_list_instance_init(GTypeInstance *instance, gpointer g_class) { GPassAttributeList *self = GPASS_ATTRIBUTE_LIST(instance); self->list = NULL; self->hash = g_hash_table_new(g_str_hash, g_str_equal); } static void attribute_list_instance_finalize(GObject *object) { GPassAttributeList *self = GPASS_ATTRIBUTE_LIST(object); GList *p; for (p = self->list; p != NULL; p = g_list_next(p)) { g_object_unref(p->data); } g_list_free(self->list); g_hash_table_destroy(self->hash); G_OBJECT_CLASS(parent_list_class)->finalize(object); } static void attribute_list_class_init(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); parent_list_class = g_type_class_peek_parent(g_class); gobject_class->finalize = attribute_list_instance_finalize; } GType gpass_attribute_list_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassAttributeListClass), NULL, NULL, attribute_list_class_init, NULL, NULL, sizeof(GPassAttributeList), 0, attribute_list_instance_init }; type = g_type_register_static(G_TYPE_OBJECT, "GPassAttributeList", &info, 0); } return type; } gint gpass_attribute_list_length(GPassAttributeList *self) { return g_list_length(self->list); } static GError * insert_to_hash(GPassAttributeList *self, GPassAttribute *attr) { GError *error = NULL; if (attr->name == NULL || attr->name[0] == '\0') { g_set_error(&error, 0, 0, _("attribute name is empty")); return error; } if (g_hash_table_lookup(self->hash, attr->name) != NULL) { g_set_error(&error, 0, 0, _("already appended attribute: %s"), attr->name); return error; } g_hash_table_insert(self->hash, attr->name, attr); g_object_ref(attr); return NULL; } GError * gpass_attribute_list_prepend(GPassAttributeList *self, GPassAttribute *attr) { GError *error = insert_to_hash(self, attr); if (error != NULL) { return error; } self->list = g_list_prepend(self->list, attr); return NULL; } GError * gpass_attribute_list_append(GPassAttributeList *self, GPassAttribute *attr) { GError *error = insert_to_hash(self, attr); if (error != NULL) { return error; } self->list = g_list_append(self->list, attr); return NULL; } GPassAttribute * gpass_attribute_list_lookup(GPassAttributeList *self, const gchar *name) { return g_hash_table_lookup(self->hash, name); } void gpass_attribute_list_remove(GPassAttributeList *self, const gchar *name) { GPassAttribute *attr = gpass_attribute_list_lookup(self, name); if (attr == NULL) { return; } self->list = g_list_remove(self->list, attr); g_hash_table_remove(self->hash, attr->name); g_object_unref(attr); } GPassAttributeListCursor * gpass_attribute_list_create_cursor(GPassAttributeList *self) { return g_object_new(GPASS_TYPE_ATTRIBUTE_LIST_CURSOR, "list", self->list, NULL); } GError * gpass_attribute_list_dump(GPassAttributeList *self, GString **buffer) { GPassAttributeListCursor *cursor = gpass_attribute_list_create_cursor(self); GError *error = NULL; while (!gpass_attribute_list_cursor_is_done(cursor)) { GPassAttribute *attr; g_object_get(cursor, "attribute", &attr, NULL); error = gpass_attribute_dump(attr, buffer); if (error != NULL) { break; } error = gpass_attribute_list_cursor_next(cursor); if (error != NULL) { break; } } g_object_unref(cursor); return error; } GError * gpass_attribute_list_load(GPassAttributeList *self, const guchar *buffer, gint buffer_len, gint *read_len) { GPassAttributeListCursor *cursor = gpass_attribute_list_create_cursor(self); const guchar *ptr = buffer, *ptr_end = buffer + buffer_len; GError *error = NULL; while (!gpass_attribute_list_cursor_is_done(cursor)) { GPassAttribute *attr; gint len; if (ptr >= ptr_end) { g_set_error(&error, 0, 0, _("buffer is too short")); goto end; } g_object_get(cursor, "attribute", &attr, NULL); error = gpass_attribute_load(attr, ptr, ptr_end - ptr, &len); if (error != NULL) { goto end; } ptr += len; error = gpass_attribute_list_cursor_next(cursor); if (error != NULL) { goto end; } } *read_len = ptr - buffer; end: g_object_unref(cursor); return error; }