source: trunk/third/evolution/e-util/e-pilot-map.c @ 16787

Revision 16787, 8.7 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16786, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/* Evolution Conduits - Pilot Map routines
3 *
4 * Copyright (C) 2000 Ximian, Inc.
5 *
6 * Authors: JP Rosevear <jpr@ximian.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
11 *
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 GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include "e-pilot-map.h"
24
25#include <string.h> /* memset(), strcmp() */
26#include <stdlib.h>
27#include <glib.h>
28#include <gnome-xml/parser.h>
29#include <libgnome/gnome-defs.h>
30#include <libgnome/gnome-util.h>
31
32typedef struct
33{
34        char *uid;
35        gboolean archived;
36        gboolean touched;
37} EPilotMapPidNode;
38
39typedef struct
40{
41        guint32 pid;
42        gboolean archived;
43        gboolean touched;
44} EPilotMapUidNode;
45
46typedef struct
47{
48        gboolean touched_only;
49        xmlNodePtr root;
50} EPilotMapWriteData;
51
52static void
53real_e_pilot_map_insert (EPilotMap *map, guint32 pid, const char *uid, gboolean archived, gboolean touch)
54{
55        char *new_uid;
56        guint32 *new_pid;
57        EPilotMapPidNode *pnode;
58        EPilotMapUidNode *unode;
59        gpointer key, value;
60
61        g_return_if_fail (map != NULL);
62        g_return_if_fail (uid != NULL);
63
64        new_pid = g_new (guint32, 1);
65        *new_pid = pid;
66
67        new_uid = g_strdup (uid);
68
69        pnode = g_new0 (EPilotMapPidNode, 1);
70        pnode->uid = new_uid;
71        pnode->archived = archived;
72        if (touch)
73                pnode->touched = TRUE;
74       
75        unode = g_new0 (EPilotMapUidNode, 1);
76        unode->pid = pid;
77        unode->archived = archived;
78        if (touch)
79                unode->touched = TRUE;
80       
81        if (g_hash_table_lookup_extended (map->pid_map, new_pid, &key, &value)) {
82                g_hash_table_remove (map->pid_map, new_pid);
83                g_free (key);
84                g_free (value);
85        }
86        if (g_hash_table_lookup_extended (map->uid_map, new_uid, &key, &value)) {
87                g_hash_table_remove (map->uid_map, new_uid);
88                g_free (key);
89                g_free (value);
90        }
91       
92        g_hash_table_insert (map->pid_map, new_pid, pnode);
93        g_hash_table_insert (map->uid_map, new_uid, unode);
94}
95
96static void
97map_set_node_timet (xmlNodePtr node, const char *name, time_t t)
98{
99        char *tstring;
100       
101        tstring = g_strdup_printf ("%ld", t);
102        xmlSetProp (node, name, tstring);
103        g_free (tstring);
104}
105
106static void
107map_sax_start_element (void *data, const xmlChar *name,
108                       const xmlChar **attrs)
109{
110        EPilotMap *map = (EPilotMap *)data;
111
112        if (!strcmp (name, "PilotMap")) {
113                while (attrs && *attrs != NULL) {
114                        const xmlChar **val = attrs;
115                       
116                        val++;
117                        if (!strcmp (*attrs, "timestamp"))
118                                map->since = (time_t)strtoul (*val, NULL, 0);
119
120                        attrs = ++val;
121                }
122        }
123         
124        if (!strcmp (name, "map")) {
125                const char *uid = NULL;
126                guint32 pid = 0;
127                gboolean archived = FALSE;
128
129                while (attrs && *attrs != NULL) {
130                        const xmlChar **val = attrs;
131                       
132                        val++;
133                        if (!strcmp (*attrs, "uid"))
134                                uid = *val;
135                       
136                        if (!strcmp (*attrs, "pilot_id"))
137                                pid = strtoul (*val, NULL, 0);
138
139                        if (!strcmp (*attrs, "archived"))
140                                archived = strtoul (*val, NULL, 0)== 1 ? TRUE : FALSE;
141                               
142                        attrs = ++val;
143                }
144
145                g_assert (uid != NULL);
146                g_assert (pid != 0 || archived);
147
148                real_e_pilot_map_insert (map, pid, uid, archived, FALSE);
149        }
150}
151
152static void
153map_write_foreach (gpointer key, gpointer value, gpointer data)
154{
155        EPilotMapWriteData *wd = data;
156        xmlNodePtr root = wd->root;
157        char *uid = key;
158        EPilotMapUidNode *unode = value;
159        xmlNodePtr mnode;
160
161        if (wd->touched_only && !unode->touched)
162                return;
163       
164        mnode = xmlNewChild (root, NULL, "map", NULL);
165        xmlSetProp (mnode, "uid", uid);
166
167        if (unode->archived) {
168                xmlSetProp (mnode, "archived", "1");
169        } else {
170                char *pidstr;
171
172                pidstr = g_strdup_printf ("%d", unode->pid);
173                xmlSetProp (mnode, "pilot_id", pidstr);
174                g_free (pidstr);
175                xmlSetProp (mnode, "archived", "0");
176        }
177}
178
179gboolean
180e_pilot_map_pid_is_archived (EPilotMap *map, guint32 pid)
181{
182        EPilotMapPidNode *pnode;
183
184        g_return_val_if_fail (map != NULL, FALSE);
185       
186        pnode = g_hash_table_lookup (map->pid_map, &pid);
187
188        if (pnode == NULL)
189                return FALSE;
190       
191        return pnode->archived;
192}
193
194gboolean
195e_pilot_map_uid_is_archived (EPilotMap *map, const char *uid)
196{
197        EPilotMapUidNode *unode;
198
199        g_return_val_if_fail (map != NULL, FALSE);
200        g_return_val_if_fail (uid != NULL, FALSE);
201       
202        unode = g_hash_table_lookup (map->uid_map, uid);
203
204        if (unode == NULL)
205                return FALSE;
206       
207        return unode->archived;
208}
209
210void
211e_pilot_map_insert (EPilotMap *map, guint32 pid, const char *uid, gboolean archived)
212{
213        real_e_pilot_map_insert (map, pid, uid, archived, TRUE);
214}
215
216void
217e_pilot_map_remove_by_pid (EPilotMap *map, guint32 pid)
218{
219        EPilotMapPidNode *pnode = NULL;
220        EPilotMapUidNode *unode = NULL;
221        gpointer pkey, ukey;
222       
223        g_return_if_fail (map != NULL);
224
225        if (!g_hash_table_lookup_extended (map->pid_map, &pid,
226                                           &pkey, (gpointer *)&pnode))
227                return;
228       
229        g_hash_table_lookup_extended (map->uid_map, pnode->uid, &ukey,
230                                      (gpointer *)&unode);
231        g_assert (unode != NULL);
232       
233        g_hash_table_remove (map->pid_map, &pid);
234        g_hash_table_remove (map->uid_map, pnode->uid);
235
236        g_free (pkey);
237        g_free (ukey);
238        g_free (pnode);
239        g_free (unode);
240}
241
242void
243e_pilot_map_remove_by_uid (EPilotMap *map, const char *uid)
244{
245        EPilotMapPidNode *pnode;
246        EPilotMapUidNode *unode;
247        gpointer pkey, ukey;
248       
249        g_return_if_fail (map != NULL);
250        g_return_if_fail (uid != NULL);
251
252        if (!g_hash_table_lookup_extended (map->uid_map, uid, &ukey, (gpointer *)&unode))
253                return;
254       
255        g_hash_table_lookup_extended (map->pid_map, &unode->pid, &pkey, (gpointer *)&pnode);
256
257        g_hash_table_remove (map->uid_map, uid);
258        g_hash_table_remove (map->pid_map, &unode->pid);
259
260        g_free (pkey);
261        g_free (ukey);
262        g_free (pnode);
263        g_free (unode);
264}
265
266
267guint32
268e_pilot_map_lookup_pid (EPilotMap *map, const char *uid, gboolean touch)
269{
270        EPilotMapUidNode *unode = NULL;
271
272        g_return_val_if_fail (map != NULL, 0);
273        g_return_val_if_fail (uid != NULL, 0);
274       
275        unode = g_hash_table_lookup (map->uid_map, uid);
276
277        if (unode == NULL)
278                return 0;
279       
280        if (touch) {
281                EPilotMapPidNode *pnode = NULL;
282               
283                pnode = g_hash_table_lookup (map->pid_map, &unode->pid);
284                if (pnode != NULL)
285                        pnode->touched = TRUE;
286                unode->touched = TRUE; 
287        }
288       
289        return unode->pid;
290}
291
292const char *
293e_pilot_map_lookup_uid (EPilotMap *map, guint32 pid, gboolean touch)
294{
295        EPilotMapPidNode *pnode = NULL;
296
297        g_return_val_if_fail (map != NULL, NULL);
298       
299        pnode = g_hash_table_lookup (map->pid_map, &pid);
300
301        if (pnode == NULL)
302                return NULL;
303       
304        if (touch) {
305                EPilotMapUidNode *unode = NULL;
306               
307                unode = g_hash_table_lookup (map->uid_map, pnode->uid);
308                g_assert (unode != NULL);
309               
310                unode->touched = TRUE;
311                pnode->touched = TRUE;
312        }
313       
314        return pnode->uid;
315}
316
317int
318e_pilot_map_read (const char *filename, EPilotMap **map)
319{
320        xmlSAXHandler handler;
321        EPilotMap *new_map;
322
323        g_return_val_if_fail (filename != NULL, -1);
324        g_return_val_if_fail (map != NULL, -1);
325
326        *map = NULL;
327        new_map = g_new0 (EPilotMap, 1);
328
329        memset (&handler, 0, sizeof (xmlSAXHandler));
330        handler.startElement = map_sax_start_element;
331
332        new_map->pid_map = g_hash_table_new (g_int_hash, g_int_equal);
333        new_map->uid_map = g_hash_table_new (g_str_hash, g_str_equal);
334
335        if (g_file_exists (filename)) {
336                if (xmlSAXUserParseFile (&handler, new_map, filename) < 0) {
337                        g_free (new_map);
338                        return -1;
339                }
340        }
341
342        new_map->write_touched_only = FALSE;
343       
344        *map = new_map;
345       
346        return 0;
347}
348               
349int
350e_pilot_map_write (const char *filename, EPilotMap *map)
351{
352        EPilotMapWriteData wd;
353        xmlDocPtr doc;
354        int ret;
355
356        g_return_val_if_fail (filename != NULL, -1);
357        g_return_val_if_fail (map != NULL, -1);
358       
359        doc = xmlNewDoc ("1.0");
360        if (doc == NULL) {
361                g_warning ("Pilot map file could not be created\n");
362                return -1;
363        }
364        doc->root = xmlNewDocNode(doc, NULL, "PilotMap", NULL);
365        map->since = time (NULL);
366        map_set_node_timet (doc->root, "timestamp", map->since);
367
368        wd.touched_only = map->write_touched_only;
369        wd.root = doc->root;
370        g_hash_table_foreach (map->uid_map, map_write_foreach, &wd);
371       
372        /* Write the file */
373        xmlSetDocCompressMode (doc, 0);
374        ret = xmlSaveFile (filename, doc);
375        if (ret < 0) {
376                g_warning ("Pilot map file '%s' could not be saved\n", filename);
377                return -1;
378        }
379       
380        xmlFreeDoc (doc);
381
382        return 0;
383}
384
385static gboolean
386foreach_remove (gpointer key, gpointer value, gpointer data)
387{
388        g_free (key);
389        g_free (value);
390
391        return TRUE;
392}
393
394void
395e_pilot_map_destroy (EPilotMap *map)
396{
397        g_return_if_fail (map != NULL);
398
399        g_hash_table_foreach_remove (map->pid_map, foreach_remove, NULL);
400        g_hash_table_foreach_remove (map->uid_map, foreach_remove, NULL);
401       
402        g_hash_table_destroy (map->pid_map);
403        g_hash_table_destroy (map->uid_map);
404        g_free (map);
405}
Note: See TracBrowser for help on using the repository browser.