1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 2002-2006 Dom Lachowicz (cinamod@hotmail.com)
6 * Jody Goldberg (jody@gnome.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2.1 of the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 #include <gsf-config.h>
24 #include <gsf/gsf-doc-meta-data.h>
25 #include <gsf/gsf-docprop-vector.h>
26 #include <gsf/gsf-impl-utils.h>
30 struct _GsfDocMetaData {
35 typedef GObjectClass GsfDocMetaDataClass;
40 char *linked_to; /* optionally NULL */
43 static GObjectClass *parent_class;
46 gsf_doc_meta_data_finalize (GObject *obj)
48 g_hash_table_destroy (GSF_DOC_META_DATA (obj)->table);
49 parent_class->finalize (obj);
53 gsf_doc_meta_data_init (GObject *obj)
55 GsfDocMetaData *meta = GSF_DOC_META_DATA (obj);
56 meta->table = g_hash_table_new_full (g_str_hash, g_str_equal,
57 NULL, (GDestroyNotify) gsf_doc_prop_free);
61 gsf_doc_meta_data_class_init (GObjectClass *gobject_class)
63 gobject_class->finalize = gsf_doc_meta_data_finalize;
64 parent_class = g_type_class_peek_parent (gobject_class);
67 GSF_CLASS(GsfDocMetaData, gsf_doc_meta_data,
68 gsf_doc_meta_data_class_init, gsf_doc_meta_data_init,
71 /**********************************************************************/
74 * gsf_doc_meta_data_new :
76 * Returns: a new metadata property collection
79 gsf_doc_meta_data_new (void)
81 return g_object_new (GSF_DOC_META_DATA_TYPE, NULL);
85 * gsf_doc_meta_data_lookup :
86 * @meta : #GsfDocMetaData
89 * Returns: the property with name @id in @meta. The caller can modify the
90 * property value and link but not the name.
93 gsf_doc_meta_data_lookup (GsfDocMetaData const *meta, char const *name)
95 g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL);
96 g_return_val_if_fail (name != NULL, NULL);
97 return g_hash_table_lookup (meta->table, name);
101 * gsf_doc_meta_data_insert :
102 * @meta : #GsfDocMetaData
106 * Take ownership of @name and @value and insert a property into @meta.
107 * If a property exists with @name, it is replaced (The link is lost)
110 gsf_doc_meta_data_insert (GsfDocMetaData *meta, char *name, GValue *value)
114 g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
115 g_return_if_fail (name != NULL);
116 prop = g_new (GsfDocProp, 1);
119 prop->linked_to = NULL;
120 g_hash_table_replace (meta->table, prop->name, prop);
124 * gsf_doc_meta_data_remove :
125 * @meta : the collection
126 * @name : the non-null string name of the property
128 * If @name does not exist in the collection, do nothing. If @name does exist,
129 * remove it and its value from the collection
132 gsf_doc_meta_data_remove (GsfDocMetaData *meta, char const *name)
134 g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
135 g_return_if_fail (name != NULL);
136 g_hash_table_remove (meta->table, name);
140 * gsf_doc_meta_data_store :
141 * @meta : #GsfDocMetaData
146 gsf_doc_meta_data_steal (GsfDocMetaData *meta, char const *name)
149 g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL);
150 g_return_val_if_fail (name != NULL, NULL);
151 prop = g_hash_table_lookup (meta->table, name);
153 g_hash_table_steal (meta->table, name);
158 * gsf_doc_meta_data_store :
159 * @meta : #GsfDocMetaData
160 * @prop : #GsfDocProp
164 gsf_doc_meta_data_store (GsfDocMetaData *meta, GsfDocProp *prop)
166 g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
167 g_return_if_fail (prop != NULL);
168 g_return_if_fail (prop != g_hash_table_lookup (meta->table, prop->name));
169 g_hash_table_replace (meta->table, prop->name, prop);
173 cb_collect_pairs (char *prop_name, GsfDocProp *prop, GPtrArray *pairs)
175 g_ptr_array_add (pairs, prop_name);
176 g_ptr_array_add (pairs, prop);
180 deref_strcmp (const char **a, const char **b)
182 return strcmp (*a, *b);
186 * gsf_doc_meta_data_foreach :
187 * @meta : the collection
188 * @func : the function called once for each element in the collection
189 * @user_data : any supplied user data or %NULL
191 * Iterate through each (key, value) pair in this collection
194 gsf_doc_meta_data_foreach (GsfDocMetaData const *meta, GHFunc func, gpointer user_data)
199 g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
201 if (g_hash_table_size (meta->table) == 0)
204 /* Sort the pairs by property name in order to generate consistent
206 pairs = g_ptr_array_new ();
207 g_hash_table_foreach (meta->table, (GHFunc)cb_collect_pairs, pairs);
209 qsort (&g_ptr_array_index (pairs, 0),
211 2 * sizeof (gpointer),
212 (GCompareFunc)deref_strcmp);
214 for (ui = 0; ui < pairs->len; ui += 2)
215 func (g_ptr_array_index (pairs, ui),
216 g_ptr_array_index (pairs, ui + 1),
219 g_ptr_array_free (pairs, TRUE);
223 * gsf_doc_meta_data_size :
224 * @meta : the collection
226 * Returns: the number of items in this collection
229 gsf_doc_meta_data_size (GsfDocMetaData const *meta)
231 g_return_val_if_fail (meta != NULL, 0);
232 return (gsize) g_hash_table_size (meta->table);
236 cb_print_property (G_GNUC_UNUSED char const *name,
237 GsfDocProp const *prop)
239 if (gsf_doc_prop_get_link (prop) != NULL)
240 g_print ("prop '%s' LINKED TO -> '%s'\n",
241 name, gsf_doc_prop_get_link (prop));
243 g_print ("prop '%s'\n", name);
245 gsf_doc_prop_dump (prop);
249 * gsf_doc_meta_dump :
250 * @meta : #GsfDocMetaData
252 * A debugging utility to dump the content of @meta via g_print
255 gsf_doc_meta_dump (GsfDocMetaData const *meta)
257 gsf_doc_meta_data_foreach (meta,
258 (GHFunc) cb_print_property, NULL);
261 /**********************************************************************/
267 * Returns: a new #GsfDocProp which the caller is responsible for freeing.
268 * Takes ownership of @name.
271 gsf_doc_prop_new (char *name)
275 g_return_val_if_fail (name != NULL, NULL);
277 prop = g_new (GsfDocProp, 1);
280 prop->linked_to = NULL;
286 * gsf_doc_prop_free :
287 * @prop : #GsfDocProp
289 * If @prop is non %NULL free the memory associated with it
292 gsf_doc_prop_free (GsfDocProp *prop)
295 g_free (prop->linked_to);
298 g_value_unset (prop->val);
307 * gsf_doc_prop_get_name :
308 * @prop : #GsfDocProp
310 * Returns: the name of the property, the caller should not modify the result.
313 gsf_doc_prop_get_name (GsfDocProp const *prop)
315 g_return_val_if_fail (prop != NULL, NULL);
320 * gsf_doc_prop_get_val :
321 * @prop : the property
323 * Returns: the value of the property, the caller should not modify the result.
326 gsf_doc_prop_get_val (GsfDocProp const *prop)
328 g_return_val_if_fail (prop != NULL, NULL);
333 * gsf_doc_prop_set_val :
334 * @prop : #GsfDocProp
337 * Assigns @val to @prop, and unsets and frees the current value.
340 gsf_doc_prop_set_val (GsfDocProp *prop, GValue *val)
342 g_return_if_fail (prop != NULL);
344 if (val != prop->val) {
345 if (prop->val != NULL) {
346 g_value_unset (prop->val);
354 * gsf_doc_prop_swap_val :
355 * @prop : #GsfDocProp
358 * Returns: the current value of @prop, and replaces it with @val
359 * Caller is responsible for unsetting and freeing the result.
362 gsf_doc_prop_swap_val (GsfDocProp *prop, GValue *val)
365 g_return_val_if_fail (prop != NULL, NULL);
373 * gsf_doc_prop_get_link :
374 * @prop : #GsfDocProp
376 * Returns: the current link descriptor of @prop. The result should not be
380 gsf_doc_prop_get_link (GsfDocProp const *prop)
382 g_return_val_if_fail (prop != NULL, NULL);
383 return prop->linked_to;
387 * gsf_doc_prop_set_link :
388 * @prop : #GsfDocProp
389 * @link : optionally %NULL
391 * Sets @prop's link to @link
394 gsf_doc_prop_set_link (GsfDocProp *prop, char *link)
396 g_return_if_fail (prop != NULL);
398 if (link != prop->linked_to) {
399 g_free (prop->linked_to);
400 prop->linked_to = link;
405 * gsf_doc_prop_dump :
406 * @prop : #GsfDocProp
408 * A debugging utility to dump @prop as text via g_print
412 gsf_doc_prop_dump (GsfDocProp const *prop)
414 GValue const *val = gsf_doc_prop_get_val (prop);
416 if (VAL_IS_GSF_DOCPROP_VECTOR ((GValue *)val)) {
417 GValueArray *va = gsf_value_get_docprop_varray (val);
420 for (i = 0 ; i < va->n_values; i++) {
421 tmp = g_strdup_value_contents (
422 g_value_array_get_nth (va, i));
423 g_print ("\t[%u] = %s\n", i, tmp);
427 tmp = g_strdup_value_contents (val);
428 g_print ("\t= %s\n", tmp);