[16769] | 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 | * |
---|
[16786] | 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. |
---|
[16769] | 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 |
---|
[16786] | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
| 15 | * General Public License for more details. |
---|
[16769] | 16 | * |
---|
[16786] | 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. |
---|
[16769] | 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 | |
---|
| 32 | typedef struct |
---|
| 33 | { |
---|
| 34 | char *uid; |
---|
| 35 | gboolean archived; |
---|
[16786] | 36 | gboolean touched; |
---|
[16769] | 37 | } EPilotMapPidNode; |
---|
| 38 | |
---|
| 39 | typedef struct |
---|
| 40 | { |
---|
| 41 | guint32 pid; |
---|
| 42 | gboolean archived; |
---|
[16786] | 43 | gboolean touched; |
---|
[16769] | 44 | } EPilotMapUidNode; |
---|
| 45 | |
---|
[16786] | 46 | typedef struct |
---|
| 47 | { |
---|
| 48 | gboolean touched_only; |
---|
| 49 | xmlNodePtr root; |
---|
| 50 | } EPilotMapWriteData; |
---|
[16769] | 51 | |
---|
| 52 | static void |
---|
[16786] | 53 | real_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 | |
---|
| 60 | g_return_if_fail (map != NULL); |
---|
| 61 | g_return_if_fail (uid != NULL); |
---|
| 62 | |
---|
[16864] | 63 | /* Keys */ |
---|
| 64 | if (pid != 0) { |
---|
| 65 | new_pid = g_new (guint32, 1); |
---|
| 66 | *new_pid = pid; |
---|
| 67 | } |
---|
[16786] | 68 | new_uid = g_strdup (uid); |
---|
| 69 | |
---|
[16864] | 70 | /* Values */ |
---|
| 71 | if (pid != 0) { |
---|
| 72 | pnode = g_new0 (EPilotMapPidNode, 1); |
---|
| 73 | pnode->uid = new_uid; |
---|
| 74 | pnode->archived = archived; |
---|
| 75 | if (touch) |
---|
| 76 | pnode->touched = TRUE; |
---|
| 77 | } |
---|
[16786] | 78 | |
---|
| 79 | unode = g_new0 (EPilotMapUidNode, 1); |
---|
| 80 | unode->pid = pid; |
---|
| 81 | unode->archived = archived; |
---|
| 82 | if (touch) |
---|
| 83 | unode->touched = TRUE; |
---|
| 84 | |
---|
[16864] | 85 | /* Insertion */ |
---|
| 86 | if (pid != 0) |
---|
| 87 | g_hash_table_insert (map->pid_map, new_pid, pnode); |
---|
[16786] | 88 | g_hash_table_insert (map->uid_map, new_uid, unode); |
---|
| 89 | } |
---|
| 90 | |
---|
| 91 | static void |
---|
[16769] | 92 | map_set_node_timet (xmlNodePtr node, const char *name, time_t t) |
---|
| 93 | { |
---|
| 94 | char *tstring; |
---|
| 95 | |
---|
| 96 | tstring = g_strdup_printf ("%ld", t); |
---|
| 97 | xmlSetProp (node, name, tstring); |
---|
[16786] | 98 | g_free (tstring); |
---|
[16769] | 99 | } |
---|
| 100 | |
---|
| 101 | static void |
---|
| 102 | map_sax_start_element (void *data, const xmlChar *name, |
---|
| 103 | const xmlChar **attrs) |
---|
| 104 | { |
---|
| 105 | EPilotMap *map = (EPilotMap *)data; |
---|
| 106 | |
---|
| 107 | if (!strcmp (name, "PilotMap")) { |
---|
| 108 | while (attrs && *attrs != NULL) { |
---|
| 109 | const xmlChar **val = attrs; |
---|
| 110 | |
---|
| 111 | val++; |
---|
| 112 | if (!strcmp (*attrs, "timestamp")) |
---|
| 113 | map->since = (time_t)strtoul (*val, NULL, 0); |
---|
| 114 | |
---|
| 115 | attrs = ++val; |
---|
| 116 | } |
---|
| 117 | } |
---|
| 118 | |
---|
| 119 | if (!strcmp (name, "map")) { |
---|
| 120 | const char *uid = NULL; |
---|
| 121 | guint32 pid = 0; |
---|
| 122 | gboolean archived = FALSE; |
---|
| 123 | |
---|
| 124 | while (attrs && *attrs != NULL) { |
---|
| 125 | const xmlChar **val = attrs; |
---|
| 126 | |
---|
| 127 | val++; |
---|
| 128 | if (!strcmp (*attrs, "uid")) |
---|
| 129 | uid = *val; |
---|
| 130 | |
---|
| 131 | if (!strcmp (*attrs, "pilot_id")) |
---|
| 132 | pid = strtoul (*val, NULL, 0); |
---|
| 133 | |
---|
| 134 | if (!strcmp (*attrs, "archived")) |
---|
| 135 | archived = strtoul (*val, NULL, 0)== 1 ? TRUE : FALSE; |
---|
| 136 | |
---|
| 137 | attrs = ++val; |
---|
| 138 | } |
---|
[16786] | 139 | |
---|
| 140 | g_assert (uid != NULL); |
---|
| 141 | g_assert (pid != 0 || archived); |
---|
| 142 | |
---|
| 143 | real_e_pilot_map_insert (map, pid, uid, archived, FALSE); |
---|
[16769] | 144 | } |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | static void |
---|
| 148 | map_write_foreach (gpointer key, gpointer value, gpointer data) |
---|
| 149 | { |
---|
[16786] | 150 | EPilotMapWriteData *wd = data; |
---|
| 151 | xmlNodePtr root = wd->root; |
---|
| 152 | char *uid = key; |
---|
| 153 | EPilotMapUidNode *unode = value; |
---|
[16769] | 154 | xmlNodePtr mnode; |
---|
| 155 | |
---|
[16786] | 156 | if (wd->touched_only && !unode->touched) |
---|
| 157 | return; |
---|
| 158 | |
---|
[16769] | 159 | mnode = xmlNewChild (root, NULL, "map", NULL); |
---|
[16786] | 160 | xmlSetProp (mnode, "uid", uid); |
---|
[16769] | 161 | |
---|
[16786] | 162 | if (unode->archived) { |
---|
| 163 | xmlSetProp (mnode, "archived", "1"); |
---|
| 164 | } else { |
---|
| 165 | char *pidstr; |
---|
[16769] | 166 | |
---|
[16786] | 167 | pidstr = g_strdup_printf ("%d", unode->pid); |
---|
| 168 | xmlSetProp (mnode, "pilot_id", pidstr); |
---|
| 169 | g_free (pidstr); |
---|
[16769] | 170 | xmlSetProp (mnode, "archived", "0"); |
---|
[16786] | 171 | } |
---|
[16769] | 172 | } |
---|
| 173 | |
---|
| 174 | gboolean |
---|
| 175 | e_pilot_map_pid_is_archived (EPilotMap *map, guint32 pid) |
---|
| 176 | { |
---|
| 177 | EPilotMapPidNode *pnode; |
---|
[16786] | 178 | |
---|
| 179 | g_return_val_if_fail (map != NULL, FALSE); |
---|
[16769] | 180 | |
---|
| 181 | pnode = g_hash_table_lookup (map->pid_map, &pid); |
---|
| 182 | |
---|
| 183 | if (pnode == NULL) |
---|
| 184 | return FALSE; |
---|
| 185 | |
---|
| 186 | return pnode->archived; |
---|
| 187 | } |
---|
| 188 | |
---|
| 189 | gboolean |
---|
| 190 | e_pilot_map_uid_is_archived (EPilotMap *map, const char *uid) |
---|
| 191 | { |
---|
| 192 | EPilotMapUidNode *unode; |
---|
[16786] | 193 | |
---|
| 194 | g_return_val_if_fail (map != NULL, FALSE); |
---|
| 195 | g_return_val_if_fail (uid != NULL, FALSE); |
---|
[16769] | 196 | |
---|
| 197 | unode = g_hash_table_lookup (map->uid_map, uid); |
---|
| 198 | |
---|
| 199 | if (unode == NULL) |
---|
| 200 | return FALSE; |
---|
| 201 | |
---|
| 202 | return unode->archived; |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | void |
---|
| 206 | e_pilot_map_insert (EPilotMap *map, guint32 pid, const char *uid, gboolean archived) |
---|
| 207 | { |
---|
[16864] | 208 | gpointer key, value; |
---|
| 209 | |
---|
| 210 | if (g_hash_table_lookup_extended (map->pid_map, &pid, &key, &value)) { |
---|
| 211 | EPilotMapPidNode *pnode = value; |
---|
| 212 | gpointer other_key, other_value; |
---|
| 213 | |
---|
| 214 | g_hash_table_remove (map->pid_map, &pid); |
---|
| 215 | |
---|
| 216 | /* In case the pid<->uid mapping is not the same anymore */ |
---|
| 217 | if (g_hash_table_lookup_extended (map->uid_map, pnode->uid, &other_key, &other_value)) { |
---|
| 218 | g_hash_table_remove (map->uid_map, pnode->uid); |
---|
| 219 | g_free (other_key); |
---|
| 220 | g_free (other_value); |
---|
| 221 | } |
---|
| 222 | |
---|
| 223 | g_free (key); |
---|
| 224 | g_free (value); |
---|
| 225 | } |
---|
| 226 | if (g_hash_table_lookup_extended (map->uid_map, uid, &key, &value)) { |
---|
| 227 | EPilotMapUidNode *unode = value; |
---|
| 228 | gpointer other_key, other_value; |
---|
| 229 | |
---|
| 230 | g_hash_table_remove (map->uid_map, uid); |
---|
| 231 | |
---|
| 232 | /* In case the pid<->uid mapping is not the same anymore */ |
---|
| 233 | if (g_hash_table_lookup_extended (map->pid_map, &unode->pid, &other_key, &other_value)) { |
---|
| 234 | g_hash_table_remove (map->pid_map, &unode->pid); |
---|
| 235 | g_free (other_key); |
---|
| 236 | g_free (other_value); |
---|
| 237 | } |
---|
| 238 | |
---|
| 239 | g_free (key); |
---|
| 240 | g_free (value); |
---|
| 241 | } |
---|
| 242 | |
---|
[16786] | 243 | real_e_pilot_map_insert (map, pid, uid, archived, TRUE); |
---|
[16769] | 244 | } |
---|
| 245 | |
---|
| 246 | void |
---|
| 247 | e_pilot_map_remove_by_pid (EPilotMap *map, guint32 pid) |
---|
[16786] | 248 | { |
---|
| 249 | EPilotMapPidNode *pnode = NULL; |
---|
| 250 | EPilotMapUidNode *unode = NULL; |
---|
| 251 | gpointer pkey, ukey; |
---|
| 252 | |
---|
| 253 | g_return_if_fail (map != NULL); |
---|
[16769] | 254 | |
---|
[16786] | 255 | if (!g_hash_table_lookup_extended (map->pid_map, &pid, |
---|
| 256 | &pkey, (gpointer *)&pnode)) |
---|
[16769] | 257 | return; |
---|
| 258 | |
---|
[16786] | 259 | g_hash_table_lookup_extended (map->uid_map, pnode->uid, &ukey, |
---|
| 260 | (gpointer *)&unode); |
---|
| 261 | g_assert (unode != NULL); |
---|
| 262 | |
---|
[16769] | 263 | g_hash_table_remove (map->pid_map, &pid); |
---|
| 264 | g_hash_table_remove (map->uid_map, pnode->uid); |
---|
| 265 | |
---|
[16786] | 266 | g_free (pkey); |
---|
| 267 | g_free (ukey); |
---|
[16769] | 268 | g_free (pnode); |
---|
| 269 | g_free (unode); |
---|
| 270 | } |
---|
| 271 | |
---|
| 272 | void |
---|
| 273 | e_pilot_map_remove_by_uid (EPilotMap *map, const char *uid) |
---|
| 274 | { |
---|
[16864] | 275 | EPilotMapPidNode *pnode = NULL; |
---|
| 276 | EPilotMapUidNode *unode = NULL; |
---|
[16786] | 277 | gpointer pkey, ukey; |
---|
[16864] | 278 | gboolean found; |
---|
[16786] | 279 | |
---|
| 280 | g_return_if_fail (map != NULL); |
---|
| 281 | g_return_if_fail (uid != NULL); |
---|
[16769] | 282 | |
---|
[16786] | 283 | if (!g_hash_table_lookup_extended (map->uid_map, uid, &ukey, (gpointer *)&unode)) |
---|
[16769] | 284 | return; |
---|
[16864] | 285 | |
---|
[16786] | 286 | g_hash_table_lookup_extended (map->pid_map, &unode->pid, &pkey, (gpointer *)&pnode); |
---|
[16769] | 287 | |
---|
| 288 | g_hash_table_remove (map->uid_map, uid); |
---|
| 289 | g_hash_table_remove (map->pid_map, &unode->pid); |
---|
| 290 | |
---|
[16864] | 291 | if (unode->pid != 0) |
---|
| 292 | g_free (pkey); |
---|
[16786] | 293 | g_free (ukey); |
---|
[16864] | 294 | |
---|
| 295 | if (unode->pid != 0) |
---|
| 296 | g_free (pnode); |
---|
[16769] | 297 | g_free (unode); |
---|
| 298 | } |
---|
| 299 | |
---|
| 300 | |
---|
| 301 | guint32 |
---|
[16786] | 302 | e_pilot_map_lookup_pid (EPilotMap *map, const char *uid, gboolean touch) |
---|
[16769] | 303 | { |
---|
| 304 | EPilotMapUidNode *unode = NULL; |
---|
[16786] | 305 | |
---|
| 306 | g_return_val_if_fail (map != NULL, 0); |
---|
| 307 | g_return_val_if_fail (uid != NULL, 0); |
---|
[16769] | 308 | |
---|
| 309 | unode = g_hash_table_lookup (map->uid_map, uid); |
---|
| 310 | |
---|
| 311 | if (unode == NULL) |
---|
| 312 | return 0; |
---|
| 313 | |
---|
[16786] | 314 | if (touch) { |
---|
| 315 | EPilotMapPidNode *pnode = NULL; |
---|
| 316 | |
---|
| 317 | pnode = g_hash_table_lookup (map->pid_map, &unode->pid); |
---|
| 318 | if (pnode != NULL) |
---|
| 319 | pnode->touched = TRUE; |
---|
| 320 | unode->touched = TRUE; |
---|
| 321 | } |
---|
| 322 | |
---|
[16769] | 323 | return unode->pid; |
---|
| 324 | } |
---|
| 325 | |
---|
| 326 | const char * |
---|
[16786] | 327 | e_pilot_map_lookup_uid (EPilotMap *map, guint32 pid, gboolean touch) |
---|
[16769] | 328 | { |
---|
| 329 | EPilotMapPidNode *pnode = NULL; |
---|
[16786] | 330 | |
---|
| 331 | g_return_val_if_fail (map != NULL, NULL); |
---|
[16769] | 332 | |
---|
| 333 | pnode = g_hash_table_lookup (map->pid_map, &pid); |
---|
| 334 | |
---|
| 335 | if (pnode == NULL) |
---|
| 336 | return NULL; |
---|
| 337 | |
---|
[16786] | 338 | if (touch) { |
---|
| 339 | EPilotMapUidNode *unode = NULL; |
---|
| 340 | |
---|
| 341 | unode = g_hash_table_lookup (map->uid_map, pnode->uid); |
---|
| 342 | g_assert (unode != NULL); |
---|
| 343 | |
---|
| 344 | unode->touched = TRUE; |
---|
| 345 | pnode->touched = TRUE; |
---|
| 346 | } |
---|
| 347 | |
---|
[16769] | 348 | return pnode->uid; |
---|
| 349 | } |
---|
| 350 | |
---|
| 351 | int |
---|
| 352 | e_pilot_map_read (const char *filename, EPilotMap **map) |
---|
| 353 | { |
---|
| 354 | xmlSAXHandler handler; |
---|
[16786] | 355 | EPilotMap *new_map; |
---|
[16769] | 356 | |
---|
[16786] | 357 | g_return_val_if_fail (filename != NULL, -1); |
---|
| 358 | g_return_val_if_fail (map != NULL, -1); |
---|
| 359 | |
---|
[16769] | 360 | *map = NULL; |
---|
[16786] | 361 | new_map = g_new0 (EPilotMap, 1); |
---|
| 362 | |
---|
[16769] | 363 | memset (&handler, 0, sizeof (xmlSAXHandler)); |
---|
| 364 | handler.startElement = map_sax_start_element; |
---|
| 365 | |
---|
| 366 | new_map->pid_map = g_hash_table_new (g_int_hash, g_int_equal); |
---|
| 367 | new_map->uid_map = g_hash_table_new (g_str_hash, g_str_equal); |
---|
| 368 | |
---|
| 369 | if (g_file_exists (filename)) { |
---|
| 370 | if (xmlSAXUserParseFile (&handler, new_map, filename) < 0) { |
---|
| 371 | g_free (new_map); |
---|
| 372 | return -1; |
---|
| 373 | } |
---|
| 374 | } |
---|
[16786] | 375 | |
---|
| 376 | new_map->write_touched_only = FALSE; |
---|
[16769] | 377 | |
---|
| 378 | *map = new_map; |
---|
| 379 | |
---|
| 380 | return 0; |
---|
| 381 | } |
---|
| 382 | |
---|
| 383 | int |
---|
| 384 | e_pilot_map_write (const char *filename, EPilotMap *map) |
---|
| 385 | { |
---|
[16786] | 386 | EPilotMapWriteData wd; |
---|
[16769] | 387 | xmlDocPtr doc; |
---|
| 388 | int ret; |
---|
[16786] | 389 | |
---|
| 390 | g_return_val_if_fail (filename != NULL, -1); |
---|
[16769] | 391 | g_return_val_if_fail (map != NULL, -1); |
---|
| 392 | |
---|
| 393 | doc = xmlNewDoc ("1.0"); |
---|
| 394 | if (doc == NULL) { |
---|
| 395 | g_warning ("Pilot map file could not be created\n"); |
---|
| 396 | return -1; |
---|
| 397 | } |
---|
| 398 | doc->root = xmlNewDocNode(doc, NULL, "PilotMap", NULL); |
---|
| 399 | map->since = time (NULL); |
---|
| 400 | map_set_node_timet (doc->root, "timestamp", map->since); |
---|
| 401 | |
---|
[16786] | 402 | wd.touched_only = map->write_touched_only; |
---|
| 403 | wd.root = doc->root; |
---|
| 404 | g_hash_table_foreach (map->uid_map, map_write_foreach, &wd); |
---|
[16769] | 405 | |
---|
| 406 | /* Write the file */ |
---|
| 407 | xmlSetDocCompressMode (doc, 0); |
---|
| 408 | ret = xmlSaveFile (filename, doc); |
---|
| 409 | if (ret < 0) { |
---|
| 410 | g_warning ("Pilot map file '%s' could not be saved\n", filename); |
---|
| 411 | return -1; |
---|
| 412 | } |
---|
| 413 | |
---|
| 414 | xmlFreeDoc (doc); |
---|
| 415 | |
---|
| 416 | return 0; |
---|
| 417 | } |
---|
| 418 | |
---|
[16786] | 419 | static gboolean |
---|
| 420 | foreach_remove (gpointer key, gpointer value, gpointer data) |
---|
| 421 | { |
---|
| 422 | g_free (key); |
---|
| 423 | g_free (value); |
---|
| 424 | |
---|
| 425 | return TRUE; |
---|
| 426 | } |
---|
| 427 | |
---|
[16769] | 428 | void |
---|
| 429 | e_pilot_map_destroy (EPilotMap *map) |
---|
| 430 | { |
---|
[16786] | 431 | g_return_if_fail (map != NULL); |
---|
| 432 | |
---|
| 433 | g_hash_table_foreach_remove (map->pid_map, foreach_remove, NULL); |
---|
| 434 | g_hash_table_foreach_remove (map->uid_map, foreach_remove, NULL); |
---|
| 435 | |
---|
[16769] | 436 | g_hash_table_destroy (map->pid_map); |
---|
| 437 | g_hash_table_destroy (map->uid_map); |
---|
| 438 | g_free (map); |
---|
| 439 | } |
---|