aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ephy-file-helpers.c32
-rw-r--r--lib/ephy-file-helpers.h4
-rw-r--r--lib/ephy-node-db.c141
-rw-r--r--lib/ephy-node-db.h9
-rw-r--r--lib/ephy-node.c148
-rw-r--r--lib/ephy-node.h7
-rw-r--r--lib/ephy-state.c44
7 files changed, 258 insertions, 127 deletions
diff --git a/lib/ephy-file-helpers.c b/lib/ephy-file-helpers.c
index 0d61f5bfc..1161f6ac7 100644
--- a/lib/ephy-file-helpers.c
+++ b/lib/ephy-file-helpers.c
@@ -190,41 +190,35 @@ ephy_file_find (const char *path,
}
gboolean
-ephy_file_save_xml (const char *xml_file, xmlDocPtr doc)
+ephy_file_switch_temp_file (const char *filename,
+ const char *filename_temp)
{
- char *tmp_file;
char *old_file;
gboolean old_exist;
gboolean retval = TRUE;
- tmp_file = g_strconcat (xml_file, ".tmp", NULL);
- old_file = g_strconcat (xml_file, ".old", NULL);
+ old_file = g_strconcat (filename, ".old", NULL);
- if (xmlSaveFormatFile (tmp_file, doc, 1) <= 0)
- {
- g_warning ("Failed to write XML data to %s", tmp_file);
- goto failed;
- }
-
- old_exist = g_file_test (xml_file, G_FILE_TEST_EXISTS);
+ old_exist = g_file_test (filename, G_FILE_TEST_EXISTS);
if (old_exist)
{
- if (rename (xml_file, old_file) < 0)
+ if (rename (filename, old_file) < 0)
{
- g_warning ("Failed to rename %s to %s", xml_file, old_file);
+ g_warning ("Failed to rename %s to %s", filename, old_file);
retval = FALSE;
goto failed;
}
}
- if (rename (tmp_file, xml_file) < 0)
+ if (rename (filename_temp, filename) < 0)
{
- g_warning ("Failed to rename %s to %s", tmp_file, xml_file);
+ g_warning ("Failed to rename %s to %s", filename_temp, filename);
- if (rename (old_file, xml_file) < 0)
+ if (rename (old_file, filename) < 0)
{
- g_warning ("Failed to restore %s from %s", xml_file, tmp_file);
+ g_warning ("Failed to restore %s from %s",
+ filename, filename_temp);
}
retval = FALSE;
goto failed;
@@ -238,10 +232,8 @@ ephy_file_save_xml (const char *xml_file, xmlDocPtr doc)
}
}
- failed:
+failed:
g_free (old_file);
- g_free (tmp_file);
return retval;
}
-
diff --git a/lib/ephy-file-helpers.h b/lib/ephy-file-helpers.h
index 6b2d17cfe..15fa16656 100644
--- a/lib/ephy-file-helpers.h
+++ b/lib/ephy-file-helpers.h
@@ -43,8 +43,8 @@ GSList *ephy_file_find (const char *path,
const char *fname,
gint maxdepth);
-gboolean ephy_file_save_xml (const char *xml_file,
- xmlDocPtr doc);
+gboolean ephy_file_switch_temp_file (const char *filename,
+ const char *filename_temp);
G_END_DECLS
diff --git a/lib/ephy-node-db.c b/lib/ephy-node-db.c
index 58ca3fe91..10276eaba 100644
--- a/lib/ephy-node-db.c
+++ b/lib/ephy-node-db.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ * Copyright (C) 2003 Christian Persch
*
* 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
@@ -19,9 +21,14 @@
*/
#include "ephy-node-db.h"
+#include "ephy-file-helpers.h"
#include "ephy-debug.h"
#include <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
static void ephy_node_db_class_init (EphyNodeDbClass *klass);
static void ephy_node_db_init (EphyNodeDb *node);
@@ -323,11 +330,11 @@ ephy_node_db_load_from_file (EphyNodeDb *db,
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
- xmlChar *name;
+ const xmlChar *name;
xmlReaderTypes type;
gboolean skip = FALSE;
- name = xmlTextReaderName (reader);
+ name = xmlTextReaderConstName (reader);
type = xmlTextReaderNodeType (reader);
if (xmlStrEqual (name, "node")
@@ -354,7 +361,6 @@ ephy_node_db_load_from_file (EphyNodeDb *db,
{
success = FALSE;
xmlFree (version);
- xmlFree (name);
break;
}
@@ -362,8 +368,6 @@ ephy_node_db_load_from_file (EphyNodeDb *db,
xmlFree (version);
}
- xmlFree (name);
-
/* next one, please */
ret = skip ? xmlTextReaderNext (reader)
: xmlTextReaderRead (reader);
@@ -375,3 +379,130 @@ ephy_node_db_load_from_file (EphyNodeDb *db,
return (success && ret == 0);
}
+
+static int
+ephy_node_db_write_to_xml_valist (EphyNodeDb *db,
+ const xmlChar *filename,
+ const xmlChar *root,
+ const xmlChar *version,
+ const xmlChar *comment,
+ EphyNode *first_node,
+ va_list argptr)
+{
+ xmlTextWriterPtr writer;
+ EphyNode *node;
+ int ret;
+
+ LOG ("Saving node db to %s", filename)
+
+ START_PROFILER ("Saving node db")
+
+ /* FIXME: do we want to turn compression on ? */
+ writer = xmlNewTextWriterFilename (filename, 0);
+ if (writer == NULL)
+ {
+ return -1;
+ }
+
+ ret = xmlTextWriterStartDocument (writer, "1.0", NULL, NULL);
+ if (ret < 0) goto out;
+
+ ret = xmlTextWriterStartElement (writer, root);
+ if (ret < 0) goto out;
+
+ ret = xmlTextWriterWriteAttribute (writer, "version", version);
+ if (ret < 0) goto out;
+
+ if (comment != NULL)
+ {
+ ret = xmlTextWriterWriteComment (writer, comment);
+ if (ret < 0) goto out;
+ }
+
+ node = first_node;
+ while (node != NULL)
+ {
+ GPtrArray *children;
+ guint n_exceptions, i;
+ GSList *exceptions = NULL;
+
+ n_exceptions = va_arg (argptr, guint);
+ for (i=0; i < n_exceptions; i++)
+ {
+ exceptions = g_slist_prepend (exceptions,
+ va_arg (argptr, EphyNode *));
+ }
+
+ children = ephy_node_get_children (node);
+ for (i=0; i < children->len; i++)
+ {
+ EphyNode *kid;
+
+ kid = g_ptr_array_index (children, i);
+
+ if (g_slist_find (exceptions, kid) == NULL)
+ {
+ ret = ephy_node_write_to_xml (kid, writer);
+ if (ret < 0) break;
+ }
+ }
+ ephy_node_thaw (node);
+ if (ret < 0) break;
+
+ g_slist_free (exceptions);
+
+ node = va_arg (argptr, EphyNode *);
+ }
+ if (ret < 0) goto out;
+
+ ret = xmlTextWriterEndElement (writer); /* root */
+ if (ret < 0) goto out;
+
+ ret = xmlTextWriterEndDocument (writer);
+ if (ret < 0) goto out;
+
+out:
+ xmlFreeTextWriter (writer);
+
+ STOP_PROFILER ("Saving node db")
+
+ return ret >= 0 ? 0 : -1;
+}
+
+int
+ephy_node_db_write_to_xml_safe (EphyNodeDb *db,
+ const xmlChar *filename,
+ const xmlChar *root,
+ const xmlChar *version,
+ const xmlChar *comment,
+ EphyNode *node, ...)
+{
+ va_list argptr;
+ int ret = 0;
+ char *tmp_file;
+
+ tmp_file = g_strconcat (filename, ".tmp", NULL);
+
+ va_start (argptr, node);
+
+ ret = ephy_node_db_write_to_xml_valist
+ (db, tmp_file, root, version, comment, node, argptr);
+
+ va_end (argptr);
+
+ if (ret < 0)
+ {
+ g_warning ("Failed to write XML data to %s", tmp_file);
+ goto failed;
+ }
+
+ if (ephy_file_switch_temp_file (filename, tmp_file) == FALSE)
+ {
+ ret = -1;
+ }
+
+failed:
+ g_free (tmp_file);
+
+ return ret;
+}
diff --git a/lib/ephy-node-db.h b/lib/ephy-node-db.h
index f5ca81107..f9df6d894 100644
--- a/lib/ephy-node-db.h
+++ b/lib/ephy-node-db.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ * Copyright (C) 2003 Christian Persch
*
* 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
@@ -61,6 +63,13 @@ gboolean ephy_node_db_load_from_file (EphyNodeDb *db,
const xmlChar *xml_root,
const xmlChar *xml_version);
+int ephy_node_db_write_to_xml_safe (EphyNodeDb *db,
+ const xmlChar *filename,
+ const xmlChar *root,
+ const xmlChar *version,
+ const xmlChar *comment,
+ EphyNode *node, ...);
+
const char *ephy_node_db_get_name (EphyNodeDb *db);
EphyNode *ephy_node_db_get_node_from_id (EphyNodeDb *db,
diff --git a/lib/ephy-node.c b/lib/ephy-node.c
index 51bd0aa5c..35cbe6936 100644
--- a/lib/ephy-node.c
+++ b/lib/ephy-node.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ * Copyright (C) 2003 Christian Persch
*
* 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
@@ -19,7 +21,7 @@
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <glib.h>
@@ -761,122 +763,134 @@ ephy_node_get_property_node (EphyNode *node,
return retval;
}
-static void
-save_parent (gulong id,
- EphyNodeParent *node_info,
- xmlNodePtr xml_node)
+typedef struct
{
- xmlNodePtr parent_xml_node;
- char *xml;
+ xmlTextWriterPtr writer;
+ int ret;
+} ForEachData;
- parent_xml_node = xmlNewChild (xml_node, NULL, "parent", NULL);
+static void
+write_parent (gulong id,
+ EphyNodeParent *node_info,
+ ForEachData* data)
+{
+ xmlTextWriterPtr writer = data->writer;
- g_static_rw_lock_reader_lock (node_info->node->lock);
+ /* there already was an error, do nothing. this works around
+ * the fact that g_hash_table_foreach cannot be cancelled.
+ */
+ if (data->ret < 0) return;
- xml = g_strdup_printf ("%ld", node_info->node->id);
- xmlSetProp (parent_xml_node, "id", xml);
- g_free (xml);
+ data->ret = xmlTextWriterStartElement (writer, "parent");
+ if (data->ret < 0) return;
+ g_static_rw_lock_reader_lock (node_info->node->lock);
+ data->ret = xmlTextWriterWriteFormatAttribute
+ (writer, "id", "%ld", node_info->node->id);
g_static_rw_lock_reader_unlock (node_info->node->lock);
+ if (data->ret < 0) return;
+
+ data->ret = xmlTextWriterEndElement (writer); /* parent */
+ if (data->ret < 0) return;
}
-void
-ephy_node_save_to_xml (EphyNode *node,
- xmlNodePtr parent_xml_node)
+int
+ephy_node_write_to_xml(EphyNode *node,
+ xmlTextWriterPtr writer)
{
- xmlNodePtr xml_node;
- char *xml;
- char xml_buf [G_ASCII_DTOSTR_BUF_SIZE];
+ xmlChar xml_buf[G_ASCII_DTOSTR_BUF_SIZE];
guint i;
+ int ret;
+ ForEachData data;
- g_return_if_fail (EPHY_IS_NODE (node));
- g_return_if_fail (parent_xml_node != NULL);
+ g_return_val_if_fail (EPHY_IS_NODE (node), -1);
+ g_return_val_if_fail (writer != NULL, -1);
g_static_rw_lock_reader_lock (node->lock);
- xml_node = xmlNewChild (parent_xml_node, NULL, "node", NULL);
+ /* start writing the node */
+ ret = xmlTextWriterStartElement (writer, "node");
+ if (ret < 0) goto out;
- xml = g_strdup_printf ("%ld", node->id);
- xmlSetProp (xml_node, "id", xml);
- g_free (xml);
+ /* write node id */
+ ret = xmlTextWriterWriteFormatAttribute (writer, "id", "%ld", node->id);
+ if (ret < 0) goto out;
- for (i = 0; i < node->properties->len; i++) {
+ /* write node properties */
+ for (i = 0; i < node->properties->len; i++)
+ {
GValue *value;
- xmlNodePtr value_xml_node;
value = g_ptr_array_index (node->properties, i);
- if (value == NULL)
- continue;
- value_xml_node = xmlNewChild (xml_node, NULL, "property", NULL);
+ if (value == NULL) continue;
- xml = g_strdup_printf ("%d", i);
- xmlSetProp (value_xml_node, "id", xml);
- g_free (xml);
+ ret = xmlTextWriterStartElement (writer, "property");
+ if (ret < 0) break;
- xmlSetProp (value_xml_node, "value_type", g_type_name (G_VALUE_TYPE (value)));
+ ret = xmlTextWriterWriteFormatAttribute (writer, "id", "%d", i);
+ if (ret < 0) break;
+
+ ret = xmlTextWriterWriteAttribute
+ (writer, "value_type", g_type_name (G_VALUE_TYPE (value)));
+ if (ret < 0) break;
switch (G_VALUE_TYPE (value))
{
case G_TYPE_STRING:
- xml = xmlEncodeEntitiesReentrant (NULL,
- g_value_get_string (value));
- xmlNodeSetContent (value_xml_node, xml);
- g_free (xml);
+ ret = xmlTextWriterWriteString
+ (writer, g_value_get_string (value));
break;
case G_TYPE_BOOLEAN:
- xml = g_strdup_printf ("%d", g_value_get_boolean (value));
- xmlNodeSetContent (value_xml_node, xml);
- g_free (xml);
+ ret = xmlTextWriterWriteFormatString
+ (writer, "%d", g_value_get_boolean (value));
break;
case G_TYPE_INT:
- xml = g_strdup_printf ("%d", g_value_get_int (value));
- xmlNodeSetContent (value_xml_node, xml);
- g_free (xml);
+ ret = xmlTextWriterWriteFormatString
+ (writer, "%d", g_value_get_int (value));
break;
case G_TYPE_LONG:
- xml = g_strdup_printf ("%ld", g_value_get_long (value));
- xmlNodeSetContent (value_xml_node, xml);
- g_free (xml);
+ ret = xmlTextWriterWriteFormatString
+ (writer, "%ld", g_value_get_long (value));
break;
case G_TYPE_FLOAT:
g_ascii_dtostr (xml_buf, sizeof (xml_buf),
g_value_get_float (value));
- xmlNodeSetContent (value_xml_node, xml_buf);
+ ret = xmlTextWriterWriteString (writer, xml_buf);
break;
case G_TYPE_DOUBLE:
g_ascii_dtostr (xml_buf, sizeof (xml_buf),
g_value_get_double (value));
- xmlNodeSetContent (value_xml_node, xml_buf);
+ ret = xmlTextWriterWriteString (writer, xml_buf);
break;
- case G_TYPE_POINTER:
- {
- EphyNode *prop_node;
-
- prop_node = g_value_get_pointer (value);
-
- g_assert (prop_node != NULL);
-
- g_static_rw_lock_reader_lock (prop_node->lock);
-
- xml = g_strdup_printf ("%ld", prop_node->id);
- xmlNodeSetContent (value_xml_node, xml);
- g_free (xml);
-
- g_static_rw_lock_reader_unlock (prop_node->lock);
- break;
- }
default:
g_assert_not_reached ();
break;
}
+ if (ret < 0) break;
+
+ ret = xmlTextWriterEndElement (writer); /* property */
+ if (ret < 0) break;
}
+ if (ret < 0) goto out;
+
+ /* now write parent node ids */
+ data.writer = writer;
+ data.ret = 0;
g_hash_table_foreach (node->parents,
- (GHFunc) save_parent,
- xml_node);
+ (GHFunc) write_parent,
+ &data);
+ ret = data.ret;
+ if (ret < 0) goto out;
+ ret = xmlTextWriterEndElement (writer); /* node */
+ if (ret < 0) goto out;
+
+out:
g_static_rw_lock_reader_unlock (node->lock);
+
+ return ret >= 0 ? 0 : -1;
}
static inline void
diff --git a/lib/ephy-node.h b/lib/ephy-node.h
index 842001665..754c3f53e 100644
--- a/lib/ephy-node.h
+++ b/lib/ephy-node.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright (C) 2003 Marco Pesenti Gritti
+ * Copyright (C) 2003 Christian Persch
*
* 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
@@ -23,6 +25,7 @@
#define EPHY_NODE_H
#include <libxml/tree.h>
+#include <libxml/xmlwriter.h>
G_BEGIN_DECLS
@@ -100,8 +103,8 @@ char *ephy_node_get_property_time (EphyNode *node,
guint property_id);
/* xml storage */
-void ephy_node_save_to_xml (EphyNode *node,
- xmlNodePtr parent_xml_node);
+int ephy_node_write_to_xml (EphyNode *node,
+ xmlTextWriterPtr writer);
EphyNode *ephy_node_new_from_xml (EphyNodeDb *db,
xmlNodePtr xml_node);
diff --git a/lib/ephy-state.c b/lib/ephy-state.c
index c797d2211..33edb87a5 100644
--- a/lib/ephy-state.c
+++ b/lib/ephy-state.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2001 Matthew Mueller
- * (C) 2002 Jorn Baayen <jorn@nl.linux.org>
- * (C) 2003 Marco Pesenti Gritti <mpeseng@tin.it>
+ * Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright (C) 2003 Marco Pesenti Gritti <mpeseng@tin.it>
*
* 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
@@ -28,7 +28,7 @@
#include <gtk/gtkwindow.h>
#include <gtk/gtkpaned.h>
-#define STATES_FILE "states.xml"
+#define EPHY_STATES_XML_FILE "states.xml"
#define EPHY_STATES_XML_ROOT "ephy_states"
#define EPHY_STATES_XML_VERSION "1.0"
@@ -50,39 +50,21 @@ static EphyNodeDb *states_db = NULL;
static void
ephy_states_save (void)
{
- xmlDocPtr doc;
- xmlNodePtr root;
- GPtrArray *children;
- int i;
char *xml_file;
- if (states == NULL) return;
-
xml_file = g_build_filename (ephy_dot_dir (),
- STATES_FILE,
+ EPHY_STATES_XML_FILE,
NULL);
- /* save nodes to xml */
- xmlIndentTreeOutput = TRUE;
- doc = xmlNewDoc ("1.0");
-
- root = xmlNewDocNode (doc, NULL, "ephy_states", NULL);
- xmlSetProp (root, "version", EPHY_STATES_XML_VERSION);
- xmlDocSetRootElement (doc, root);
-
- children = ephy_node_get_children (states);
- for (i = 0; i < children->len; i++)
- {
- EphyNode *kid;
-
- kid = g_ptr_array_index (children, i);
-
- ephy_node_save_to_xml (kid, root);
- }
- ephy_node_thaw (states);
+ ephy_node_db_write_to_xml_safe
+ (states_db, xml_file,
+ EPHY_STATES_XML_ROOT,
+ EPHY_STATES_XML_VERSION,
+ NULL, /* comment */
+ states, 0,
+ NULL);
- ephy_file_save_xml (xml_file, doc);
- g_free (xml_file);
+ g_free (xml_file);
}
static EphyNode *
@@ -120,7 +102,7 @@ ensure_states (void)
char *xml_file;
xml_file = g_build_filename (ephy_dot_dir (),
- STATES_FILE,
+ EPHY_STATES_XML_FILE,
NULL);
states_db = ephy_node_db_new (EPHY_NODE_DB_STATES);