From 846d2da27f3081614b08c9bb167cb21d3148e99e Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 30 Aug 2011 22:02:49 +0300 Subject: [PATCH] * mu-threader, mu-util: cleanups --- src/mu-threader.c | 98 ++++++++++++++++++++++---------------------- src/mu-util.c | 102 +++++++++++++++++++++++----------------------- src/mu-util.h | 12 ++++++ 3 files changed, 113 insertions(+), 99 deletions(-) diff --git a/src/mu-threader.c b/src/mu-threader.c index adfec75a..fd29d145 100644 --- a/src/mu-threader.c +++ b/src/mu-threader.c @@ -41,11 +41,11 @@ * Msg4 (child of Msg2) => 00001:00001 * Msg5 (child of Msg4) => 00001:00001:00000 * Msg6 => 00002 - * + * * the padding-0's are added to make them easy to sort using strcmp; * the number hexadecimal numbers, and the length of the 'segments' * (the parts separated by the ':') is equal to ceil(log_16(matchnum)) - * + * */ @@ -67,10 +67,10 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield) g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) || sortfield == MU_MSG_FIELD_ID_NONE, FALSE); - + /* step 1 */ id_table = create_containers (iter); - + /* step 2 -- the root_set is the list of children without parent */ root_set = find_root_set (id_table); @@ -78,22 +78,22 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield) /* step 4: prune empty containers */ root_set = prune_empty_containers (root_set); - + /* sort root set */ if (sortfield != MU_MSG_FIELD_ID_NONE) root_set = mu_container_sort (root_set, sortfield, NULL, FALSE); - + /* step 5: group root set by subject */ //group_root_set_by_subject (root_set); /* sort */ mu_msg_iter_reset (iter); /* go all the way back */ - + /* finally, deliver the docid => thread-path hash */ thread_ids = mu_container_thread_info_hash_new (root_set, matchnum); - + g_hash_table_destroy (id_table); /* step 3*/ return thread_ids; @@ -119,11 +119,11 @@ assert_no_duplicates (GHashTable *ids) GHashTable *hash; hash = g_hash_table_new (g_direct_hash, g_direct_equal); - + g_hash_table_foreach (ids, (GHFunc)check_dup, hash); - + g_hash_table_destroy (hash); } @@ -140,7 +140,7 @@ find_or_create_referred (GHashTable *id_table, const char *msgid, g_return_val_if_fail (msgid, NULL); - c = g_hash_table_lookup (id_table, msgid); + c = g_hash_table_lookup (id_table, msgid); *created = !c; if (!c) { c = mu_container_new (NULL, 0, msgid); @@ -148,7 +148,7 @@ find_or_create_referred (GHashTable *id_table, const char *msgid, /* assert_no_duplicates (id_table); */ } - + return c; } @@ -162,13 +162,13 @@ find_or_create (GHashTable *id_table, MuMsg *msg, guint docid) g_return_val_if_fail (msg, NULL); g_return_val_if_fail (docid != 0, NULL); - + msgid = mu_msg_get_msgid (msg); if (!msgid) msgid = mu_msg_get_path (msg); /* fake it */ - - c = g_hash_table_lookup (id_table, msgid); - + + c = g_hash_table_lookup (id_table, msgid); + /* If id_table contains an empty MuContainer for this ID: * * * Store this message in the MuContainer's message slot. */ if (c) { @@ -200,14 +200,14 @@ find_or_create (GHashTable *id_table, MuMsg *msg, guint docid) c = mu_container_new (msg, docid, msgid); g_hash_table_insert (id_table, (gpointer)msgid, c); /* assert_no_duplicates (id_table); */ - + return c; } } static gboolean child_elligible (MuContainer *parent, MuContainer *child, gboolean created) -{ +{ if (!parent || !child) return FALSE; if (child->parent) @@ -230,25 +230,25 @@ handle_references (GHashTable *id_table, MuContainer *c) const GSList *refs, *cur; MuContainer *parent; gboolean created; - + refs = mu_msg_get_references (c->msg); - if (!refs) + if (!refs) return; /* nothing to do */ - + /* For each element in the message's References field: Find a MuContainer object for the given Message-ID: If there's one in id_table use that; Otherwise, make (and index) one with a null Message. */ - - /* go over over our list of refs, until 1 before the last... */ + + /* go over over our list of refs, until 1 before the last... */ created = FALSE; for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) { MuContainer *child; child = find_or_create_referred (id_table, (gchar*)cur->data, &created); - + /*Link the References field's MuContainers together in * the order implied by the References header. @@ -261,13 +261,13 @@ handle_references (GHashTable *id_table, MuContainer *c) as a child of the other, don't add the link. */ if (child_elligible (parent, child, created)) - parent = mu_container_append_children (parent, child); + parent = mu_container_append_children (parent, child); parent = child; } - /* 'parent' points to the last ref: our direct parent; - + /* 'parent' points to the last ref: our direct parent; + Set the parent of this message to be the last element in References. Note that this message may have a parent already: this can happen because we saw this ID in a @@ -276,12 +276,12 @@ handle_references (GHashTable *id_table, MuContainer *c) we can be more definitive, so throw away the old parent and use this new one. Find this MuContainer in the parent's children list, and unlink it. - + Note that this could cause this message to now have no parent, if it has no references field, but some message referred to it as the non-first element of its references. (Which would have been some kind of lie...) - + Note that at all times, the various ``parent'' and ``child'' fields must be kept inter-consistent. */ @@ -302,24 +302,24 @@ create_containers (MuMsgIter *iter) g_str_equal, NULL, (GDestroyNotify)mu_container_destroy); - + for (mu_msg_iter_reset (iter); !mu_msg_iter_is_done (iter); mu_msg_iter_next (iter)) { - + MuContainer *c; MuMsg *msg; unsigned docid; - + /* 1.A */ - msg = mu_msg_iter_get_msg (iter, NULL); + msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */ docid = mu_msg_iter_get_docid (iter); - + c = find_or_create (id_table, msg, docid); /* 1.B and C */ if (c) - handle_references (id_table, c); - } + handle_references (id_table, c); + } return id_table; } @@ -330,7 +330,7 @@ static void filter_root_set (const gchar *msgid, MuContainer *c, MuContainer **root_set) { if (c->parent) - return; + return; if (*root_set == NULL) { *root_set = c; @@ -358,25 +358,25 @@ static gboolean prune_maybe (MuContainer *c) { MuContainer *cur; - + for (cur = c->child; cur; cur = cur->next) { - if (cur->flags & MU_CONTAINER_FLAG_DELETE) + if (cur->flags & MU_CONTAINER_FLAG_DELETE) c = mu_container_remove_child (c, cur); - else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) + else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) c = mu_container_splice_children (c, cur); } - + /* don't touch containers with messages */ - if (c->msg) + if (c->msg) return TRUE; - + /* A. If it is an msg-less container with no children, mark it * for deletion. */ if (!c->child) { c->flags |= MU_CONTAINER_FLAG_DELETE; return TRUE; } - + /* B. If the MuContainer has no Message, but does have * children, remove this container but promote its * children to this level (that is, splice them in to @@ -388,9 +388,9 @@ prune_maybe (MuContainer *c) */ if (c->child->next) /* ie., > 1 child */ return TRUE; - + c->flags |= MU_CONTAINER_FLAG_SPLICE; - + return TRUE; } @@ -401,11 +401,11 @@ prune_empty_containers (MuContainer *root_set) MuContainer *cur; mu_container_foreach (root_set, (MuContainerForeachFunc)prune_maybe, NULL); - + /* and prune the root_set itself... */ for (cur = root_set; cur; cur = cur->next) { - - if (cur->flags & MU_CONTAINER_FLAG_DELETE) + + if (cur->flags & MU_CONTAINER_FLAG_DELETE) root_set = mu_container_remove_sibling (root_set, cur); else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) { diff --git a/src/mu-util.c b/src/mu-util.c index e747dc91..496950c1 100644 --- a/src/mu-util.c +++ b/src/mu-util.c @@ -1,6 +1,6 @@ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ /* -** +** ** Copyright (C) 2008-2011 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify @@ -63,12 +63,12 @@ do_wordexp (const char *path) /* g_debug ("%s: path is empty", __FUNCTION__); */ return NULL; } - + if (wordexp (path, &wexp, 0) != 0) { /* g_debug ("%s: expansion failed for %s", __FUNCTION__, path); */ return NULL; } - + /* we just pick the first one */ dir = g_strdup (wexp.we_wordv[0]); @@ -76,7 +76,7 @@ do_wordexp (const char *path) so we have to allow for a tiny leak here on that platform... maybe instead of __APPLE__ it should be __BSD__?*/ -#ifndef __APPLE__ +#ifndef __APPLE__ wordfree (&wexp); #endif /*__APPLE__*/ @@ -102,16 +102,16 @@ mu_util_dir_expand (const char *path) /* don't try realpath if the dir does not exist */ if (access (dir, F_OK) != 0) return dir; - + /* now resolve any symlinks, .. etc. */ if (realpath (dir, resolved) == NULL) { g_debug ("%s: could not get realpath for '%s': %s", __FUNCTION__, dir, strerror(errno)); g_free (dir); return NULL; - } else + } else g_free (dir); - + return g_strdup (resolved); } @@ -120,7 +120,7 @@ char* mu_util_create_tmpdir (void) { gchar *dirname; - + dirname = g_strdup_printf ("%s%cmu-%d%c%x", g_get_tmp_dir(), G_DIR_SEPARATOR, @@ -141,7 +141,7 @@ const char* mu_util_cache_dir (void) { static char cachedir [PATH_MAX]; - + snprintf (cachedir, sizeof(cachedir), "%s%cmu-%u", g_get_tmp_dir(), G_DIR_SEPARATOR, getuid()); @@ -170,9 +170,9 @@ mu_util_init_system (void) } /* g_debug ("setting G_SLICE to always-malloc"); */ #endif /*!__linux__*/ - + g_type_init (); - + return TRUE; } @@ -182,10 +182,10 @@ mu_util_check_dir (const gchar* path, gboolean readable, gboolean writeable) { int mode; struct stat statbuf; - - if (!path) + + if (!path) return FALSE; - + mode = F_OK | (readable ? R_OK : 0) | (writeable ? W_OK : 0); if (access (path, mode) != 0) { @@ -197,7 +197,7 @@ mu_util_check_dir (const gchar* path, gboolean readable, gboolean writeable) g_debug ("Cannot stat %s: %s", path, strerror (errno)); return FALSE; } - + return S_ISDIR(statbuf.st_mode) ? TRUE: FALSE; } @@ -207,18 +207,18 @@ mu_util_guess_maildir (void) { const gchar *mdir1; gchar *mdir2; - + /* first, try MAILDIR */ mdir1 = g_getenv ("MAILDIR"); if (mdir1 && mu_util_check_dir (mdir1, TRUE, FALSE)) return g_strdup (mdir1); - + /* then, try ~/Maildir */ mdir2 = mu_util_dir_expand ("~/Maildir"); if (mu_util_check_dir (mdir2, TRUE, FALSE)) return mdir2; - + /* nope; nothing found */ return NULL; } @@ -235,7 +235,7 @@ mu_util_guess_mu_homedir (void) if (!home) MU_WRITE_LOG ("failed to determine homedir"); - + return g_strdup_printf ("%s%c%s", home ? home : ".", G_DIR_SEPARATOR, ".mu"); } @@ -244,10 +244,10 @@ gboolean mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn) { struct stat statbuf; - + g_return_val_if_fail (path, FALSE); - /* if it exists, it must be a readable dir */ + /* if it exists, it must be a readable dir */ if (stat (path, &statbuf) == 0) { if ((!S_ISDIR(statbuf.st_mode)) || (access (path, W_OK|R_OK) != 0)) { @@ -256,8 +256,8 @@ mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn) "directory: %s", path); return FALSE; } - } - + } + if (g_mkdir_with_parents (path, mode) != 0) { if (!nowarn) g_warning ("failed to create %s: %s", @@ -274,22 +274,22 @@ mu_util_str_from_strv (const gchar **params) { GString *str; int i; - + g_return_val_if_fail (params, NULL); - + if (!params[0]) return g_strdup (""); - + str = g_string_sized_new (64); /* just a guess */ - + for (i = 0; params[i]; ++i) { if (i>0) g_string_append_c (str, ' '); g_string_append (str, params[i]); - } - + } + return g_string_free (str, FALSE); } @@ -299,7 +299,7 @@ mu_util_create_writeable_fd (const char* path, mode_t mode, { errno = 0; /* clear! */ g_return_val_if_fail (path, -1); - + if (overwrite) return open (path, O_WRONLY|O_CREAT|O_TRUNC, mode); else @@ -315,11 +315,11 @@ mu_util_is_local_file (const char* path) * still considered local) */ if (g_ascii_strncasecmp ("file://", path, strlen("file://")) == 0) return TRUE; - + if (access (path, R_OK) == 0) return TRUE; - return FALSE; + return FALSE; } @@ -329,11 +329,11 @@ mu_util_play (const char *path, gboolean allow_local, gboolean allow_remote) #ifndef XDGOPEN g_warning ("opening files not supported (xdg-open missing)"); return FALSE; -#else +#else gboolean rv; GError *err; const gchar *argv[3]; - + g_return_val_if_fail (path, FALSE); g_return_val_if_fail (mu_util_is_local_file (path) || allow_remote, FALSE); @@ -342,11 +342,11 @@ mu_util_play (const char *path, gboolean allow_local, gboolean allow_remote) argv[0] = XDGOPEN; argv[1] = path; argv[2] = NULL; - + err = NULL; rv = g_spawn_async (NULL, (gchar**)&argv, NULL, 0, NULL, NULL, NULL, &err); - + if (!rv) { g_warning ("failed to spawn xdg-open: %s", err->message ? err->message : "error"); @@ -362,14 +362,14 @@ unsigned char mu_util_get_dtype_with_lstat (const char *path) { struct stat statbuf; - + g_return_val_if_fail (path, DT_UNKNOWN); - + if (lstat (path, &statbuf) != 0) { g_warning ("stat failed on %s: %s", path, strerror(errno)); return DT_UNKNOWN; } - + /* we only care about dirs, regular files and links */ if (S_ISREG (statbuf.st_mode)) return DT_REG; @@ -387,10 +387,10 @@ mu_util_locale_is_utf8 (void) { const gchar *dummy; static int is_utf8 = -1; - - if (G_UNLIKELY(is_utf8 == -1)) + + if (G_UNLIKELY(is_utf8 == -1)) is_utf8 = g_get_charset(&dummy) ? 1 : 0; - + return is_utf8 ? TRUE : FALSE; } @@ -399,19 +399,19 @@ mu_util_fputs_encoded (const char *str, FILE *stream) { char *conv; int rv; - + g_return_val_if_fail (str, FALSE); g_return_val_if_fail (stream, FALSE); - + /* g_get_charset return TRUE when the locale is UTF8 */ - if (mu_util_locale_is_utf8()) + if (mu_util_locale_is_utf8()) rv = fputs (str, stream); else { /* charset is _not_ utf8, so we actually have to * convert it..*/ GError *err; unsigned bytes; err = NULL; - + conv = g_locale_from_utf8 (str, -1, &bytes, NULL, &err); if (err) { /* conversion failed; this happens because is @@ -427,7 +427,7 @@ mu_util_fputs_encoded (const char *str, FILE *stream) rv = fputs (conv, stream); g_free (conv); } - + if (rv == EOF) { /* note, apparently, does not set errno */ g_printerr ("fputs failed"); return FALSE; @@ -442,7 +442,7 @@ print_args (FILE *stream, const char *frm, va_list args) { gchar *str; gboolean rv; - + str = g_strdup_vprintf (frm, args); rv = mu_util_fputs_encoded (str, stream); @@ -460,7 +460,7 @@ mu_util_print_encoded (const char *frm, ...) gboolean rv; g_return_val_if_fail (frm, FALSE); - + va_start (args, frm); rv = print_args (stdout, frm, args); va_end (args); @@ -475,10 +475,12 @@ mu_util_printerr_encoded (const char *frm, ...) gboolean rv; g_return_val_if_fail (frm, FALSE); - + va_start (args, frm); rv = print_args (stderr, frm, args); va_end (args); return rv; } + + diff --git a/src/mu-util.h b/src/mu-util.h index 2f5b9095..2ad06c9b 100644 --- a/src/mu-util.h +++ b/src/mu-util.h @@ -255,6 +255,18 @@ typedef gpointer XapianDocument; typedef gpointer XapianEnquire; +/* print a warning for a GError, and free it */ +#define MU_HANDLE_G_ERROR(GE) \ + do { \ + if (!(GE)) \ + g_warning ("%s:%u: an error occured in %s", \ + __FILE__, __LINE__, __FUNCTION__); \ + else { \ + g_warning ("error %u: %s", (GE)->code, (GE)->message); \ + g_error_free ((GE)); \ + } \ + } while (0) + /**