From 6226754a25432ef1e874065f26d67908ef59c370 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Thu, 3 Mar 2011 21:22:11 +0200 Subject: [PATCH] * WIP: mu-contacts; add the following: return timestamp callback and add regexp filtering capabilities --- src/mu-cmd.c | 10 ++++++--- src/mu-contacts.c | 52 +++++++++++++++++++++++++++++++++++++++-------- src/mu-contacts.h | 20 +++++++++++++----- src/mu-store.cc | 2 +- src/mu-str.h | 13 +++++++++++- 5 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/mu-cmd.c b/src/mu-cmd.c index adea7717..44aedf77 100644 --- a/src/mu-cmd.c +++ b/src/mu-cmd.c @@ -132,11 +132,14 @@ mu_cmd_mkdir (MuConfig *opts) static void -each_contact (const char *email, const char *name, gpointer data) +each_contact (const char *email, const char *name, time_t tstamp, gpointer data) { - g_print ("%s %s\n", email, name ? name : ""); + g_print ("%u: %s %s\n", (unsigned)tstamp, email, name ? name : ""); } + + + MuExitCode mu_cmd_cfind (MuConfig *opts) { @@ -157,7 +160,8 @@ mu_cmd_cfind (MuConfig *opts) return MU_EXITCODE_ERROR; } - mu_contacts_foreach (contacts, (MuContactsForeachFunc)each_contact, NULL); + mu_contacts_foreach (contacts, (MuContactsForeachFunc)each_contact, NULL, + opts->params[1]); mu_contacts_destroy (contacts); return MU_OK; diff --git a/src/mu-contacts.c b/src/mu-contacts.c index 48b5afd5..6cdc624a 100644 --- a/src/mu-contacts.c +++ b/src/mu-contacts.c @@ -22,6 +22,7 @@ #include "mu-contacts.h" #include "mu-util.h" +#include "mu-str.h" #define MU_CONTACTS_NAME_KEY "name" #define MU_CONTACTS_TIMESTAMP_KEY "timestamp" @@ -123,7 +124,7 @@ mu_contacts_add (MuContacts *self, const char* name, const char *email, * empty name */ cinfo = (ContactInfo*) g_hash_table_lookup (self->_hash, email); if (!cinfo || - (cinfo->_tstamp < tstamp && name && name[0] != '\0')) { + (cinfo->_tstamp < tstamp && !mu_str_is_empty(name))) { g_hash_table_insert (self->_hash, g_strdup(email), contact_info_new (name, tstamp)); return self->_dirty = TRUE; @@ -135,30 +136,65 @@ mu_contacts_add (MuContacts *self, const char* name, const char *email, struct _EachContactData { MuContactsForeachFunc _func; gpointer _user_data; + GRegex *_rx; }; typedef struct _EachContactData EachContactData; -static void +static void /* email will never be NULL, but ci->_name may be */ each_contact (const char* email, ContactInfo *ci, EachContactData *ecdata) { - ecdata->_func (email, ci->_name, ecdata->_user_data); + /* ignore this contact if we have a regexp, and it matches + * neither email nor name (if we have a name) */ + while (ecdata->_rx) { /* note, only once */ + if (g_regex_match (ecdata->_rx, email, 0, NULL)) + break; /* email matches? continue! */ + if (!ci->_name) + return; /* email did not match, no name? ignore this one */ + if (g_regex_match (ecdata->_rx,ci->_name, 0, NULL)) + break; /* name matches? continue! */ + return; /* nothing matched, ignore this one */ + } + + ecdata->_func (email, ci->_name, ci->_tstamp, ecdata->_user_data); } -void +gboolean mu_contacts_foreach (MuContacts *self, MuContactsForeachFunc func, - gpointer user_data) + gpointer user_data, const char *pattern) { EachContactData ecdata; - g_return_if_fail (self); - g_return_if_fail (func); + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (func, FALSE); + if (pattern) { + GError *err; + err = NULL; + ecdata._rx = g_regex_new + (pattern, G_REGEX_CASELESS|G_REGEX_EXTENDED|G_REGEX_OPTIMIZE, + 0, &err); + if (!ecdata._rx) { + g_warning ("error in regexp '%s': %s", pattern, err->message); + g_error_free (err); + return FALSE; + } + } else + ecdata._rx = NULL; + ecdata._func = func; ecdata._user_data = user_data; g_hash_table_foreach (self->_hash, (GHFunc) each_contact, &ecdata); -} + + if (ecdata._rx) + g_regex_unref (ecdata._rx); + return TRUE; +} + + + + static void each_keyval (const char *email, ContactInfo *cinfo, MuContacts *self) diff --git a/src/mu-contacts.h b/src/mu-contacts.h index e5a183df..36c60bde 100644 --- a/src/mu-contacts.h +++ b/src/mu-contacts.h @@ -62,19 +62,29 @@ gboolean mu_contacts_add (MuContacts *contacts, const char* name, const char *em */ void mu_contacts_destroy (MuContacts *contacts); - -typedef void (*MuContactsForeachFunc) (const char *email, const char *name, +/** + * call called for mu_contacts_foreach; returns the e-mail address, + * name (which may be NULL) and the timestamp for the address + * + */ +typedef void (*MuContactsForeachFunc) (const char *email, const char *name, time_t tstamp, gpointer user_data); /** - * call a function for each contact + * call a function for either each contact, or each contact satisfying + * a regular expression, * * @param contacts contacts object * @param func callback function to be called for each * @param user_data user data to pass to the callback + * @param pattern a regular expression which matches either the e-mail + * or name, to filter out contacts, or NULL to not do any filtering. + * + * @return TRUE if the function succeeded, or FALSE if the provide + * regular expression was invalid (and not NULL) */ -void mu_contacts_foreach (MuContacts *contacts, MuContactsForeachFunc func, - gpointer user_data); +gboolean mu_contacts_foreach (MuContacts *contacts, MuContactsForeachFunc func, + gpointer user_data, const char* pattern); G_END_DECLS diff --git a/src/mu-store.cc b/src/mu-store.cc index 4fc485fa..dd25b203 100644 --- a/src/mu-store.cc +++ b/src/mu-store.cc @@ -496,7 +496,7 @@ each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc) msgdoc->_doc->add_term (std::string (*pfxp + escaped, 0, MU_STORE_MAX_TERM_LENGTH)); g_free (escaped); - + /* store it also in our contacts cache */ if (msgdoc->_store->_contacts) mu_contacts_add (msgdoc->_store->_contacts, diff --git a/src/mu-str.h b/src/mu-str.h index 715d3168..97ba53a5 100644 --- a/src/mu-str.h +++ b/src/mu-str.h @@ -223,7 +223,7 @@ time_t mu_str_date_parse_hdwmy (const char* str); * * @param str a string with a size, such a "100", "100Kb", "1Mb" * - * @return + * @return the corresponding time_t value (as a guint64) */ guint64 mu_str_size_parse_kmg (const char* str); @@ -250,6 +250,17 @@ const char* mu_str_fullpath_s (const char* path, const char* name); char* mu_str_escape_c_literal (const gchar* str) G_GNUC_WARN_UNUSED_RESULT; + +/** + * macro to check whether the string is empty, ie. if it's NULL or + * it's length is 0 + * + * @param S a string + * + * @return TRUE if the string is empty, FALSE otherwise + */ +#define mu_str_is_empty(S) ((!(S)||!(S)[0])?TRUE:FALSE) + G_END_DECLS #endif /*__MU_STR_H__*/