diff options
Diffstat (limited to 'e-util/e-meta.c')
-rw-r--r-- | e-util/e-meta.c | 517 |
1 files changed, 0 insertions, 517 deletions
diff --git a/e-util/e-meta.c b/e-util/e-meta.c deleted file mode 100644 index 2b0dce5c30..0000000000 --- a/e-util/e-meta.c +++ /dev/null @@ -1,517 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU 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 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 "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <glib.h> - -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xmlmemory.h> - -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#include <gal/util/e-xml-utils.h> -#include <gal/util/e-util.h> -#include "e-meta.h" - -static GObjectClass *e_meta_parent_class; - -struct _meta_data { - struct _meta_data *next; - - char *md_key; - char *md_value; -}; - -struct _EMetaPrivate { - char *path; - struct _meta_data *data; - gulong sync_id; - /* if set, we wont try and save/etc */ - unsigned int deleted:1; -}; - -static int meta_save(EMeta *em) -{ - struct _EMetaPrivate *p = em->priv; - xmlDocPtr doc; - xmlNodePtr root, work; - struct _meta_data *md; - int res; - char *dir; - struct stat st; - - if (p->deleted) - return 0; - - /* since we can, build the full path if we need to */ - dir = g_path_get_dirname(p->path); - if (stat(dir, &st) == -1) { - e_mkdir_hier(dir, 0777); - g_free(dir); - } - - /* of course, saving in xml is overkill, but everyone loves this shit ... */ - - doc = xmlNewDoc("1.0"); - root = xmlNewDocNode(doc, NULL, "e-meta-data", NULL); - xmlDocSetRootElement(doc, root); - - md = p->data; - while (md) { - work = xmlNewChild(root, NULL, "item", NULL); - xmlSetProp(work, "name", md->md_key); - xmlSetProp(work, "value", md->md_value); - md = md->next; - } - - res = e_xml_save_file(p->path, doc); - if (res != 0) - g_warning("Could not save folder meta-data `%s': %s", p->path, g_strerror(errno)); - - xmlFreeDoc(doc); - - return res; -} - -static int meta_load(EMeta *em) -{ - struct _EMetaPrivate *p = em->priv; - struct _meta_data *tail, *md; - xmlDocPtr doc; - xmlNodePtr root, work; - char *name, *val; - - doc = xmlParseFile(p->path); - if (doc == NULL) - return -1; - - root = xmlDocGetRootElement(doc); - if (root == NULL || strcmp(root->name, "e-meta-data")) { - xmlFreeDoc(doc); - errno = EINVAL; - return -1; - } - - work = root->children; - tail = (struct _meta_data *)&p->data; - while (work) { - if (strcmp(work->name, "item") == 0) { - name = xmlGetProp(work, "name"); - val = xmlGetProp(work, "value"); - if (name && val) { - md = g_malloc(sizeof(*md)); - md->md_key = g_strdup(name); - md->md_value = g_strdup(val); - md->next = NULL; - tail->next = md; - tail = md; - } - if (name) - xmlFree(name); - if (val) - xmlFree(val); - } - work = work->next; - } - - xmlFreeDoc(doc); - - return 0; -} - -static struct _meta_data *meta_find(EMeta *em, const char *key, struct _meta_data **mpp) -{ - struct _meta_data *mp = (struct _meta_data *)&em->priv->data; - struct _meta_data *md = mp->next; - - while (md && strcmp(md->md_key, key) != 0) { - mp = md; - md = md->next; - } - - *mpp = mp; - - return md; -} - -static void meta_free(struct _meta_data *md) -{ - g_free(md->md_key); - g_free(md->md_value); - g_free(md); -} - -static void -e_meta_init (EMeta *em) -{ - em->priv = g_malloc0(sizeof(*em->priv)); -} - -static void -e_meta_finalise(GObject *crap) -{ - EMeta *em = (EMeta *)crap; - struct _EMetaPrivate *p = em->priv; - struct _meta_data *md, *mn; - - if (p->sync_id != 0) - e_meta_sync(em); - - md = p->data; - while (md) { - mn = md->next; - meta_free(md); - md = mn; - } - - g_free(p->path); - g_free(p); - e_meta_parent_class->finalize((GObject *)em); -} - -static void -e_meta_class_init (EMetaClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS(klass); - - e_meta_parent_class = g_type_class_ref (G_TYPE_OBJECT); - - ((GObjectClass *)klass)->finalize = e_meta_finalise; -} - -static GTypeInfo e_meta_type_info = { - sizeof (EMetaClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) e_meta_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMeta), - 0, /* n_preallocs */ - (GInstanceInitFunc) e_meta_init -}; - -static GType e_meta_type; - -GType -e_meta_get_type (void) -{ - return e_meta_type?e_meta_type:(e_meta_type = g_type_register_static (G_TYPE_OBJECT, "EMeta", &e_meta_type_info, 0)); -} - -/** - * e_meta_new: - * @path: full path to meta-data storage object. - * - * Create a new meta-data storage object. Any existing meta-data stored for - * this key will be loaded. - * - * Return value: - **/ -EMeta * -e_meta_new(const char *path) -{ - EMeta *em; - - em = g_object_new(e_meta_get_type(), NULL); - em->priv->path = g_strdup(path); - meta_load(em); - - return em; -} - -static gboolean -meta_flush(EMeta *em) -{ - em->priv->sync_id = 0; - meta_save(em); - - return FALSE; -} - -/* returns TRUE if the value changed */ -static int meta_set(EMeta *em, const char *key, const char *val) -{ - struct _EMetaPrivate *p = em->priv; - struct _meta_data *md, *mp; - - md = meta_find(em, key, &mp); - if (md == NULL) { - /* already unset / or new case */ - if (val == NULL) - return FALSE; - md = g_malloc0(sizeof(*md)); - md->md_key = g_strdup(key); - md->next = p->data; - p->data = md; - } else if (val == NULL) { - /* unset case */ - mp->next = md->next; - meta_free(md); - return TRUE; - } else if (strcmp(md->md_value, val) == 0) { - /* unchanged value */ - return FALSE; - } else { - /* changed value */ - g_free(md->md_value); - } - md->md_value = g_strdup(val); - - return TRUE; -} - -/* get a value, returns NULL if it doesn't exist */ -static const char *meta_get(EMeta *em, const char *key) -{ - struct _meta_data *md, *mp; - - md = meta_find(em, key, &mp); - - return md?md->md_value:NULL; -} - -/** - * e_meta_set: - * @em: - * @key: - * @...: value, key, value, ..., NULL. - * - * Set any number of meta-data key-value pairs. - * Unset a key by passing a value of NULL. - * - * If the meta-data set changes as a result of this - * call, then a sync will be implicitly queued for - * a later time. - **/ -void -e_meta_set(EMeta *em, const char *key, ...) -{ - struct _EMetaPrivate *p = em->priv; - const char *val; - va_list ap; - int changed = FALSE; - - va_start(ap, key); - while (key != NULL) { - val = va_arg(ap, const char *); - changed = meta_set(em, key, val); - key = va_arg(ap, const char *); - } - va_end(ap); - - /* todo: could do changed events ? */ - - if (changed && p->sync_id == 0) - p->sync_id = g_timeout_add(2000, (GSourceFunc)meta_flush, em); -} - -/** - * e_meta_get: - * @em: - * @key: - * @...: value, key, value, ..., NULL. - * - * Get any number of meta-data key-value pairs. - **/ -void -e_meta_get(EMeta *em, const char *key, ...) -{ - const char **valp; - va_list ap; - - va_start(ap, key); - while (key) { - valp = va_arg(ap, const char **); - *valp = meta_get(em, key); - key = va_arg(ap, const char *); - } - va_end(ap); -} - -/** - * e_meta_get_bool: - * @em: - * @key: - * @def: - * - * Get a boolean value at @key, with a default fallback @def. - * - * If the default value is used, then it will become the persistent - * new value for the key. - * - * Return value: The value of the key, or if the key was not - * previously set, then the new value of the key, @def. - **/ -gboolean -e_meta_get_bool(EMeta *em, const char *key, gboolean def) -{ - const char *v; - - v = meta_get(em, key); - /* this forces the value to become 'static' from first use */ - if (v == NULL) { - e_meta_set_bool(em, key, def); - return def; - } - - return atoi(v); -} - -/** - * e_meta_set_bool: - * @em: - * @key: - * @val: - * - * Helper to set a boolean value. Boolean TRUE is mapped to - * the string "1", FALSE to "0". - **/ -void -e_meta_set_bool(EMeta *em, const char *key, gboolean val) -{ - e_meta_set(em, key, val?"1":"0", NULL); -} - -/** - * e_meta_sync: - * @em: - * - * Force an explicit and immediate sync of the meta-data to disk. - * - * This is not normally required unless part of transactional - * processing, as updates will always be flushed to disk automatically. - * - * Return value: 0 on success. - **/ -int -e_meta_sync(EMeta *em) -{ - struct _EMetaPrivate *p = em->priv; - - if (p->sync_id != 0) { - g_source_remove(p->sync_id); - p->sync_id = 0; - } - - return meta_save(em); -} - -static GHashTable *e_meta_table; - -static char *meta_filename(const char *base, const char *key) -{ - const char *p; - char *keyp, *o, c; - - p = key; - o = keyp = alloca(strlen(key)+8); - - while ( (c = *p++) ) { - if (c == '/') - c = '_'; - *o++ = c; - } - strcpy(o, ".emeta"); - o = g_build_filename(base, keyp, NULL); - - return o; -} - -static void -meta_weak_notify(char *path, void *o) -{ - g_hash_table_remove(e_meta_table, path); - g_free(path); -} - -/** - * e_meta_data_lookup: - * @base: Base storage directory. - * @key: key for file. - * - * Lookup a meta-data object from a storage directory. - * - * Return value: The metadata object. - **/ -EMeta *e_meta_data_find(const char *base, const char *key) -{ - EMeta *em; - char *path; - - if (e_meta_table == NULL) - e_meta_table = g_hash_table_new(g_str_hash, g_str_equal); - - path = meta_filename(base, key); - em = g_hash_table_lookup(e_meta_table, path); - if (em) { - g_free(path); - g_object_ref(em); - return em; - } - - em = e_meta_new(path); - g_hash_table_insert(e_meta_table, path, em); - g_object_weak_ref((GObject *)em, (GWeakNotify)meta_weak_notify, path); - - return em; -} - -/** - * e_meta_data_delete: - * @base: - * @key: - * - * Delete a key from storage. If the key is still cached, it will be - * marked as deleted, and will not be saved from then on. - **/ -void e_meta_data_delete(const char *base, const char *key) -{ - EMeta *em; - char *path; - - path = meta_filename(base, key); - - if (e_meta_table && (em = g_hash_table_lookup(e_meta_table, path))) { - if (em->priv->sync_id) { - g_source_remove(em->priv->sync_id); - em->priv->sync_id = 0; - } - em->priv->deleted = TRUE; - } - - unlink(path); - g_free(path); -} |