/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gsf-doc-meta-data.c: * * Copyright (C) 2002-2006 Dom Lachowicz (cinamod@hotmail.com) * Jody Goldberg (jody@gnome.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2.1 of the GNU Lesser General Public * License as published by the Free Software Foundation. * * 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 Lesser 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 */ #include #include #include #include struct _GsfDocMetaData { GObject base; GHashTable *table; }; typedef GObjectClass GsfDocMetaDataClass; struct _GsfDocProp { char *name; GValue *val; char *linked_to; /* optionally NULL */ }; static GObjectClass *parent_class; static void gsf_doc_meta_data_finalize (GObject *obj) { g_hash_table_destroy (GSF_DOC_META_DATA (obj)->table); parent_class->finalize (obj); } static void gsf_doc_meta_data_init (GObject *obj) { GsfDocMetaData *meta = GSF_DOC_META_DATA (obj); meta->table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsf_doc_prop_free); } static void gsf_doc_meta_data_class_init (GObjectClass *gobject_class) { gobject_class->finalize = gsf_doc_meta_data_finalize; parent_class = g_type_class_peek_parent (gobject_class); } GSF_CLASS(GsfDocMetaData, gsf_doc_meta_data, gsf_doc_meta_data_class_init, gsf_doc_meta_data_init, G_TYPE_OBJECT) /**********************************************************************/ /** * gsf_doc_meta_data_new : * * Returns: a new metadata property collection **/ GsfDocMetaData * gsf_doc_meta_data_new (void) { return g_object_new (GSF_DOC_META_DATA_TYPE, NULL); } /** * gsf_doc_meta_data_lookup : * @meta : #GsfDocMetaData * @name : * * Returns: the property with name @id in @meta. The caller can modify the * property value and link but not the name. **/ GsfDocProp * gsf_doc_meta_data_lookup (GsfDocMetaData const *meta, char const *name) { g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL); g_return_val_if_fail (name != NULL, NULL); return g_hash_table_lookup (meta->table, name); } /** * gsf_doc_meta_data_insert : * @meta : #GsfDocMetaData * @name : * @value : #GValue * * Take ownership of @name and @value and insert a property into @meta. * If a property exists with @name, it is replaced (The link is lost) **/ void gsf_doc_meta_data_insert (GsfDocMetaData *meta, char *name, GValue *value) { GsfDocProp *prop; g_return_if_fail (IS_GSF_DOC_META_DATA (meta)); g_return_if_fail (name != NULL); prop = g_new (GsfDocProp, 1); prop->name = name; prop->val = value; prop->linked_to = NULL; g_hash_table_replace (meta->table, prop->name, prop); } /** * gsf_doc_meta_data_remove : * @meta : the collection * @name : the non-null string name of the property * * If @name does not exist in the collection, do nothing. If @name does exist, * remove it and its value from the collection **/ void gsf_doc_meta_data_remove (GsfDocMetaData *meta, char const *name) { g_return_if_fail (IS_GSF_DOC_META_DATA (meta)); g_return_if_fail (name != NULL); g_hash_table_remove (meta->table, name); } /** * gsf_doc_meta_data_store : * @meta : #GsfDocMetaData * @name : * **/ GsfDocProp * gsf_doc_meta_data_steal (GsfDocMetaData *meta, char const *name) { GsfDocProp *prop; g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL); g_return_val_if_fail (name != NULL, NULL); prop = g_hash_table_lookup (meta->table, name); if (NULL != prop) g_hash_table_steal (meta->table, name); return prop; } /** * gsf_doc_meta_data_store : * @meta : #GsfDocMetaData * @prop : #GsfDocProp * **/ void gsf_doc_meta_data_store (GsfDocMetaData *meta, GsfDocProp *prop) { g_return_if_fail (IS_GSF_DOC_META_DATA (meta)); g_return_if_fail (prop != NULL); g_return_if_fail (prop != g_hash_table_lookup (meta->table, prop->name)); g_hash_table_replace (meta->table, prop->name, prop); } /** * gsf_doc_meta_data_foreach : * @meta : the collection * @func : the function called once for each element in the collection * @user_data : any supplied user data or %NULL * * Iterate through each (key, value) pair in this collection **/ void gsf_doc_meta_data_foreach (GsfDocMetaData const *meta, GHFunc func, gpointer user_data) { g_return_if_fail (IS_GSF_DOC_META_DATA (meta)); g_hash_table_foreach (meta->table, func, user_data); } /** * gsf_doc_meta_data_size : * @meta : the collection * * Returns: the number of items in this collection **/ gsize gsf_doc_meta_data_size (GsfDocMetaData const *meta) { g_return_val_if_fail (meta != NULL, 0); return (gsize) g_hash_table_size (meta->table); } static void cb_print_property (G_GNUC_UNUSED char const *name, GsfDocProp const *prop) { if (gsf_doc_prop_get_link (prop) != NULL) g_print ("prop '%s' LINKED TO -> '%s'\n", name, gsf_doc_prop_get_link (prop)); else g_print ("prop '%s'\n", name); gsf_doc_prop_dump (prop); } /** * gsf_doc_meta_dump : * @meta : #GsfDocMetaData * * A debugging utility to dump the content of @meta via g_print **/ void gsf_doc_meta_dump (GsfDocMetaData const *meta) { gsf_doc_meta_data_foreach (meta, (GHFunc) cb_print_property, NULL); } /**********************************************************************/ /** * gsf_doc_prop_new : * @name : * * Returns: a new #GsfDocProp which the caller is responsible for freeing. * Takes ownership of @name. **/ GsfDocProp * gsf_doc_prop_new (char *name) { GsfDocProp *prop; g_return_val_if_fail (name != NULL, NULL); prop = g_new (GsfDocProp, 1); prop->name = name; prop->val = NULL; prop->linked_to = NULL; return prop; } /** * gsf_doc_prop_free : * @prop : #GsfDocProp * * If @prop is non %NULL free the memory associated with it **/ void gsf_doc_prop_free (GsfDocProp *prop) { if (NULL != prop) { g_free (prop->linked_to); if (prop->val) { g_value_unset (prop->val); g_free (prop->val); } g_free (prop->name); g_free (prop); } } /** * gsf_doc_prop_get_name : * @prop : #GsfDocProp * * Returns: the name of the property, the caller should not modify the result. **/ char const * gsf_doc_prop_get_name (GsfDocProp const *prop) { g_return_val_if_fail (prop != NULL, NULL); return prop->name; } /** * gsf_doc_prop_get_val : * @prop : the property * * Returns: the value of the property, the caller should not modify the result. **/ GValue const * gsf_doc_prop_get_val (GsfDocProp const *prop) { g_return_val_if_fail (prop != NULL, NULL); return prop->val; } /** * gsf_doc_prop_set_val : * @prop : #GsfDocProp * @val : #GValue * * Assigns @val to @prop, and unsets and frees the current value. **/ void gsf_doc_prop_set_val (GsfDocProp *prop, GValue *val) { g_return_if_fail (prop != NULL); if (val != prop->val) { if (prop->val != NULL) { g_value_unset (prop->val); g_free (prop->val); } prop->val = val; } } /** * gsf_doc_prop_swap_val : * @prop : #GsfDocProp * @val : #GValue * * Returns: the current value of @prop, and replaces it with @val * Caller is responsible for unsetting and freeing the result. **/ GValue * gsf_doc_prop_swap_val (GsfDocProp *prop, GValue *val) { GValue *old_val; g_return_val_if_fail (prop != NULL, NULL); old_val = prop->val; prop->val = val; return old_val; } /** * gsf_doc_prop_get_link : * @prop : #GsfDocProp * * Returns: the current link descriptor of @prop. The result should not be * freed or modified. **/ char const * gsf_doc_prop_get_link (GsfDocProp const *prop) { g_return_val_if_fail (prop != NULL, NULL); return prop->linked_to; } /** * gsf_doc_prop_set_link : * @prop : #GsfDocProp * @link : optionally %NULL * * Sets @prop's link to @link **/ void gsf_doc_prop_set_link (GsfDocProp *prop, char *link) { g_return_if_fail (prop != NULL); if (link != prop->linked_to) { g_free (prop->linked_to); prop->linked_to = link; } } /** * gsf_doc_prop_dump : * @prop : #GsfDocProp * * A debugging utility to dump @prop as text via g_print * New in 1.14.2 **/ void gsf_doc_prop_dump (GsfDocProp const *prop) { GValue const *val = gsf_doc_prop_get_val (prop); char *tmp; if (VAL_IS_GSF_DOCPROP_VECTOR ((GValue *)val)) { GValueArray *va = gsf_value_get_docprop_varray (val); unsigned i; for (i = 0 ; i < va->n_values; i++) { tmp = g_strdup_value_contents ( g_value_array_get_nth (va, i)); g_print ("\t[%u] = %s\n", i, tmp); g_free (tmp); } } else { tmp = g_strdup_value_contents (val); g_print ("\t= %s\n", tmp); g_free (tmp); } }