From 20e39933e53f72a416f7ad3c1daa3e811c8419cd Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 20 Nov 2010 16:37:23 +0200 Subject: [PATCH] * many: fix unit tests, add synonyms (WIP -- not working yet) --- src/mu-msg-flags.c | 86 +++++++++++++++++++++++++++++++++------------- src/mu-msg-flags.h | 31 ++++++++++++++++- src/mu-query.cc | 81 +++++++++++++++++++++++++++++-------------- src/mu-store.cc | 32 +++++++++-------- 4 files changed, 167 insertions(+), 63 deletions(-) diff --git a/src/mu-msg-flags.c b/src/mu-msg-flags.c index e975df7d..11af61da 100644 --- a/src/mu-msg-flags.c +++ b/src/mu-msg-flags.c @@ -42,8 +42,7 @@ MuMsgFlags mu_msg_flag_from_char (char k) { switch (k) { - case 'N': return MU_MSG_FLAG_NEW; - + case 'N': return MU_MSG_FLAG_NEW; case 'P': return MU_MSG_FLAG_PASSED; case 'R': return MU_MSG_FLAG_REPLIED; case 'S': return MU_MSG_FLAG_SEEN; @@ -61,21 +60,22 @@ mu_msg_flag_from_char (char k) } } -char -mu_msg_flag_to_char (MuMsgFlags flag) -{ + +const char* +mu_msg_flag_to_name (MuMsgFlags flag) +{ switch (flag) { - case MU_MSG_FLAG_NEW: return 'N'; - case MU_MSG_FLAG_PASSED: return 'P'; - case MU_MSG_FLAG_REPLIED: return 'R'; - case MU_MSG_FLAG_SEEN: return 'S'; - case MU_MSG_FLAG_TRASHED: return 'T'; - case MU_MSG_FLAG_DRAFT: return 'D'; - case MU_MSG_FLAG_FLAGGED: return 'F'; + case MU_MSG_FLAG_NEW: return "new"; + case MU_MSG_FLAG_PASSED: return "passed"; + case MU_MSG_FLAG_REPLIED: return "replied"; + case MU_MSG_FLAG_SEEN: return "seen"; + case MU_MSG_FLAG_TRASHED: return "trashed"; + case MU_MSG_FLAG_DRAFT: return "draft"; + case MU_MSG_FLAG_FLAGGED: return "flagged"; - case MU_MSG_FLAG_SIGNED: return 'Z'; - case MU_MSG_FLAG_ENCRYPTED: return 'X'; - case MU_MSG_FLAG_HAS_ATTACH: return 'A'; + case MU_MSG_FLAG_SIGNED: return "signed"; + case MU_MSG_FLAG_ENCRYPTED: return "encrypted"; + case MU_MSG_FLAG_HAS_ATTACH: return "attach"; default: g_warning ("%s: unknown flag 0x%x", __FUNCTION__, flag); @@ -83,6 +83,27 @@ mu_msg_flag_to_char (MuMsgFlags flag) } } +char +mu_msg_flag_char (MuMsgFlags flag) +{ + switch (flag) { + case MU_MSG_FLAG_NEW: return 'N'; + case MU_MSG_FLAG_PASSED: return 'P'; + case MU_MSG_FLAG_REPLIED: return 'R'; + case MU_MSG_FLAG_SEEN: return 'S'; + case MU_MSG_FLAG_TRASHED: return 'T'; + case MU_MSG_FLAG_DRAFT: return 'D'; + case MU_MSG_FLAG_FLAGGED: return 'F'; + + case MU_MSG_FLAG_SIGNED: return 'Z'; + case MU_MSG_FLAG_ENCRYPTED: return 'X'; + case MU_MSG_FLAG_HAS_ATTACH: return 'A'; + + default: + g_warning ("%s: unknown flag 0x%x", __FUNCTION__, flag); + return 0; + } +} const char* mu_msg_flags_to_str_s (MuMsgFlags flags) @@ -93,7 +114,7 @@ mu_msg_flags_to_str_s (MuMsgFlags flags) for (i = j = 0; i != G_N_ELEMENTS(ALL_FLAGS); ++i) { if (flags & ALL_FLAGS[i]) { char k; - if ((k = mu_msg_flag_to_char (ALL_FLAGS[i])) == 0) + if ((k = mu_msg_flag_char (ALL_FLAGS[i])) == 0) return NULL; buf[j++] = k; } @@ -110,7 +131,7 @@ mu_msg_flags_from_str (const char* str) for (flags = MU_MSG_FLAG_NONE; str && *str; ++str) { MuMsgFlags flag; - if ((flag = mu_msg_flag_to_char (*str)) == 0) { + if ((flag = mu_msg_flag_char (*str)) == 0) { flags = 0; break; } @@ -121,6 +142,19 @@ mu_msg_flags_from_str (const char* str) } +void +mu_msg_flags_foreach (MuMsgFlagsForeachFunc func, gpointer user_data) +{ + int i; + + g_return_if_fail (func); + + for (i = 0; i != G_N_ELEMENTS(ALL_FLAGS); ++i) + func (ALL_FLAGS[i], user_data); +} + + + /* * is this a 'new' msg or a 'cur' msg?; if new, we return * (in info) a ptr to the info part @@ -202,12 +236,18 @@ mu_msg_flags_from_file (const char* path) cursor += 2; /* jump past 2, */ while (*cursor) { switch (*cursor) { - case 'P': flags |= MU_MSG_FLAG_PASSED; break; - case 'T': flags |= MU_MSG_FLAG_TRASHED; break; - case 'R': flags |= MU_MSG_FLAG_REPLIED; break; - case 'S': flags |= MU_MSG_FLAG_SEEN; break; - case 'D': flags |= MU_MSG_FLAG_DRAFT; break; - case 'F': flags |= MU_MSG_FLAG_FLAGGED; break; + case 'P': flags |= MU_MSG_FLAG_PASSED; + break; + case 'T': flags |= MU_MSG_FLAG_TRASHED; + break; + case 'R': flags |= MU_MSG_FLAG_REPLIED; + break; + case 'S': flags |= MU_MSG_FLAG_SEEN; + break; + case 'D': flags |= MU_MSG_FLAG_DRAFT; + break; + case 'F': flags |= MU_MSG_FLAG_FLAGGED; + break; } ++cursor; } diff --git a/src/mu-msg-flags.h b/src/mu-msg-flags.h index 520d24e8..5dceab70 100644 --- a/src/mu-msg-flags.h +++ b/src/mu-msg-flags.h @@ -112,7 +112,35 @@ const char* mu_msg_flags_to_str_s (MuMsgFlags flags) G_GNUC_CONST; * * @return the char for this flag, or 0 if not found */ -char mu_msg_flags_char (MuMsgFlags flag); +char mu_msg_flag_char (MuMsgFlags flag) G_GNUC_CONST; + + + +/** + * get a string describing this flag + * + * @param flag a single flag (not OR'ed) + * + * @return a string describing this flag, e.g., + * MU_MSG_FLAG_ATTACH=>"attach" + */ +const char* mu_msg_flag_to_name (MuMsgFlags flag) G_GNUC_CONST; + + + + +typedef void (*MuMsgFlagsForeachFunc) + (MuMsgFlags flag, gpointer user_data); + +/** + * call a function for each available message flag + * + * @param func a function to call (callback) + * @param user_data user pointer passed to the callback + */ +void mu_msg_flags_foreach (MuMsgFlagsForeachFunc func, gpointer user_data); + + /** * get the Maildir flags from a mailfile. The flags are as specified @@ -128,6 +156,7 @@ char mu_msg_flags_char (MuMsgFlags flag); */ MuMsgFlags mu_msg_flags_from_file (const char* pathname) G_GNUC_PURE; + /** * is the message flag a file flag? ie. encoded in the filename * diff --git a/src/mu-query.cc b/src/mu-query.cc index 7a80806b..72bfe315 100644 --- a/src/mu-query.cc +++ b/src/mu-query.cc @@ -57,7 +57,8 @@ init_mu_query (MuQuery *mqx, const char* dbpath) memset (mqx->_sorters, 0, sizeof(mqx->_sorters)); mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix, (gpointer)mqx->_qparser); -////// FIXME + + ////// FIXME // g_print ("synonyms:"); // for (Xapian::TermIterator iter = mqx->_db->synonym_keys_begin(); // iter != mqx->_db->synonym_keys_end(); ++iter) { @@ -102,7 +103,7 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) { return mqx->_qparser->parse_query (searchexpr, Xapian::QueryParser::FLAG_BOOLEAN | - Xapian::QueryParser::FLAG_PHRASE | + // Xapian::QueryParser::FLAG_PHRASE | Xapian::QueryParser::FLAG_AUTO_SYNONYMS | Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE); @@ -117,41 +118,71 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) { static void add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser) { - static char pfx[] = "\0\0"; - static char shortcut[] = "\0\0"; - if (!mu_msg_field_xapian_index(mfid) && !mu_msg_field_xapian_term(mfid) && !mu_msg_field_xapian_contact(mfid)) return; - - pfx[0] = mu_msg_field_xapian_prefix (mfid); - shortcut[0] = mu_msg_field_shortcut (mfid); try { - - if (mfid == MU_MSG_FIELD_ID_MSGID || - mfid == MU_MSG_FIELD_ID_MAILDIR || - mu_msg_field_type (mfid) != MU_MSG_FIELD_TYPE_STRING || - mu_msg_field_xapian_contact(mfid)) { - qparser->add_boolean_prefix - (mu_msg_field_name(mfid), pfx); - qparser->add_boolean_prefix (shortcut, pfx); + const std::string pfx + (1, mu_msg_field_xapian_prefix (mfid)); + const std::string shortcut + (1, mu_msg_field_shortcut (mfid)); - /* make the empty string match this field too*/ - qparser->add_prefix ("", pfx); - - } else { - - qparser->add_boolean_prefix + if (mfid == MU_MSG_FIELD_ID_FLAGS) { + qparser->add_prefix (mu_msg_field_name(mfid), pfx); qparser->add_prefix (shortcut, pfx); - - /* make the empty string match this field too*/ + } else if (mfid == MU_MSG_FIELD_ID_MAILDIR || + mfid == MU_MSG_FIELD_ID_MSGID) { + qparser->add_boolean_prefix + (mu_msg_field_name(mfid), pfx); + qparser->add_boolean_prefix (shortcut, pfx); + } else { + qparser->add_boolean_prefix + (mu_msg_field_name(mfid), pfx); + qparser->add_boolean_prefix (shortcut, pfx); qparser->add_prefix ("", pfx); } - } MU_XAPIAN_CATCH_BLOCK; + + // try { + // switch (mfid) { + + // case MU_MSG_FIELD_ID_FLAGS: + // case MU_MSG_FIELD_ID_MSGID: + // case MU_MSG_FIELD_ID_MAILDIR: + // qparser->add_prefix (shortcut, pfx); + + // } + + // if (mfid == MU_MSG_FIELD_ID_FLAGS ) { + + // return; + // } else if (mfid == MU_MSG_FIELD_ID_MSGID || + // mfid == MU_MSG_FIELD_ID_MAILDIR) { + + + // mu_msg_field_type (mfid) != MU_MSG_FIELD_TYPE_STRING || + // mu_msg_field_xapian_contact(mfid)) { + // qparser->add_boolean_prefix + // (mu_msg_field_name(mfid), pfx); + // qparser->add_boolean_prefix (shortcut, pfx); + + // /* make the empty string match this field too*/ + // qparser->add_prefix ("", pfx); + + // } else { + + // qparser->add_boolean_prefix + // (mu_msg_field_name(mfid), pfx); + // qparser->add_prefix (shortcut, pfx); + + // /* make the empty string match this field too*/ + // qparser->add_prefix ("", pfx); + // } + + // } MU_XAPIAN_CATCH_BLOCK; } MuQuery* diff --git a/src/mu-store.cc b/src/mu-store.cc index 42a4108b..4d6159ac 100644 --- a/src/mu-store.cc +++ b/src/mu-store.cc @@ -30,6 +30,7 @@ #include "mu-store.h" #include "mu-util.h" #include "mu-msg-str.h" +#include "mu-msg-flags.h" /* number of new messages after which we commit to the database */ #define MU_STORE_TRX_SIZE 6666 @@ -50,19 +51,20 @@ struct _MuStore { static void -add_synonyms (MuStore *store) +each_flag (MuMsgFlags flag, Xapian::WritableDatabase *db) { std::string pfx (1, mu_msg_field_xapian_prefix (MU_MSG_FIELD_ID_FLAGS)); - store->_db->add_synonym (pfx + "n", pfx + "new"); - store->_db->add_synonym (pfx + "unread", pfx + "n"); + db->add_synonym (pfx + mu_msg_flag_to_name (flag), + pfx + (std::string(1, mu_msg_flag_char (flag)))); +} - store->_db->add_synonym (pfx + "attach", pfx + "a"); - store->_db->add_synonym (pfx + "attachment", pfx + "a"); - - store->_db->add_synonym ("Bfoo", "Bbar"); - store->_db->add_synonym ("Gnew", "Gn"); +static void +add_synonyms (MuStore *store) +{ + mu_msg_flags_foreach ((MuMsgFlagsForeachFunc)each_flag, + store->_db); } static gboolean @@ -103,8 +105,8 @@ mu_store_new (const char* xpath) try { store = g_new0(MuStore,1); - store->_db = new Xapian::WritableDatabase (xpath, - Xapian::DB_CREATE_OR_OPEN); + store->_db = new Xapian::WritableDatabase + (xpath,Xapian::DB_CREATE_OR_OPEN); if (!check_version (store)) { mu_store_destroy (store); return NULL; @@ -175,7 +177,8 @@ mu_store_version (MuStore *store) v = store->_db->get_metadata (MU_XAPIAN_VERSION_KEY); g_free (store->_version); - return store->_version = v.empty() ? NULL : g_strdup (v.c_str()); + return store->_version = + v.empty() ? NULL : g_strdup (v.c_str()); } MU_XAPIAN_CATCH_BLOCK; @@ -309,7 +312,7 @@ add_terms_values_body (Xapian::Document& doc, MuMsg *msg, char *norm; if (mu_msg_get_flags(msg) & MU_MSG_FLAG_ENCRYPTED) - return; /* don't store encrypted bodies */ + return; /* ignore encrypted bodies */ str = mu_msg_get_body_text (msg); if (!str) /* FIXME: html->txt fallback needed */ @@ -323,7 +326,8 @@ add_terms_values_body (Xapian::Document& doc, MuMsg *msg, norm = mu_msg_str_normalize (str, TRUE); termgen.index_text_without_positions - (norm, 1, std::string(1,mu_msg_field_xapian_prefix(mfid))); + (norm, 1, + std::string(1, mu_msg_field_xapian_prefix(mfid))); g_free (norm); } @@ -532,7 +536,7 @@ mu_store_set_timestamp (MuStore *store, const char* msgpath, g_return_if_fail (msgpath); try { - char buf[24]; + char buf[21]; sprintf (buf, "%" G_GUINT64_FORMAT, (guint64)stamp); store->_db->set_metadata (msgpath, buf);