* mu-threader, mu-util: cleanups

This commit is contained in:
Dirk-Jan C. Binnema 2011-08-30 22:02:49 +03:00
parent 6a13866235
commit 846d2da27f
3 changed files with 113 additions and 99 deletions

View File

@ -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) {

View File

@ -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 <djcb@djcbsoftware.nl>
**
** 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;
}

View File

@ -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)
/**