From 7c185590e4bd72df14722894a04a7cbd3aa5f27a Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Fri, 4 Mar 2022 00:04:30 +0200 Subject: [PATCH] lib/mu-msg: update to use mu-message-fields Remove mu-msg-fields.[ch] and update sources to use mu-message-fields. --- lib/mu-msg-doc.cc | 29 +-- lib/mu-msg-doc.hh | 17 +- lib/mu-msg-fields.c | 425 -------------------------------------------- lib/mu-msg-fields.h | 292 ------------------------------ lib/mu-msg-file.cc | 177 +++++++++--------- lib/mu-msg-file.hh | 14 +- lib/mu-msg.cc | 108 +++++------ lib/mu-msg.hh | 27 ++- 8 files changed, 190 insertions(+), 899 deletions(-) delete mode 100644 lib/mu-msg-fields.c delete mode 100644 lib/mu-msg-fields.h diff --git a/lib/mu-msg-doc.cc b/lib/mu-msg-doc.cc index 066fb9f8..b40bc5ca 100644 --- a/lib/mu-msg-doc.cc +++ b/lib/mu-msg-doc.cc @@ -23,7 +23,7 @@ #include #include -#include "mu-msg-fields.h" +#include "mu-message.hh" #include "mu-msg-doc.hh" #include "utils/mu-util.h" @@ -32,6 +32,7 @@ #include "utils/mu-xapian-utils.hh" using namespace Mu; +using namespace Mu::Message; struct Mu::MuMsgDoc { MuMsgDoc(Xapian::Document* doc) : _doc(doc) {} @@ -61,13 +62,12 @@ Mu::mu_msg_doc_destroy(MuMsgDoc* self) } gchar* -Mu::mu_msg_doc_get_str_field(MuMsgDoc* self, MuMsgFieldId mfid) +Mu::mu_msg_doc_get_str_field(MuMsgDoc* self, Field::Id field_id) { g_return_val_if_fail(self, NULL); - g_return_val_if_fail(mu_msg_field_id_is_valid(mfid), NULL); // disable this check: - // g_return_val_if_fail (mu_msg_field_is_string(mfid), NULL); + // g_return_val_if_fail (mu_msg_field_is_string(field_id), NULL); // because it's useful to get numerical field as strings, // for example when sorting (which is much faster if don't // have to convert to numbers first, esp. when it's a date @@ -75,41 +75,42 @@ Mu::mu_msg_doc_get_str_field(MuMsgDoc* self, MuMsgFieldId mfid) return xapian_try( [&] { - const std::string s(self->doc().get_value(mfid)); + const auto value_no{message_field(field_id).value_no()}; + const std::string s(self->doc().get_value(value_no)); return s.empty() ? NULL : g_strdup(s.c_str()); }, (gchar*)nullptr); } GSList* -Mu::mu_msg_doc_get_str_list_field(MuMsgDoc* self, MuMsgFieldId mfid) +Mu::mu_msg_doc_get_str_list_field(MuMsgDoc* self, Field::Id field_id) { g_return_val_if_fail(self, NULL); - g_return_val_if_fail(mu_msg_field_id_is_valid(mfid), NULL); - g_return_val_if_fail(mu_msg_field_is_string_list(mfid), NULL); + g_return_val_if_fail(message_field(field_id).type == Field::Type::StringList, NULL); return xapian_try( [&] { /* return a comma-separated string as a GSList */ - const std::string s(self->doc().get_value(mfid)); + const auto value_no{message_field(field_id).value_no()}; + const std::string s(self->doc().get_value(value_no)); return s.empty() ? NULL : mu_str_to_list(s.c_str(), ',', TRUE); }, (GSList*)nullptr); } gint64 -Mu::mu_msg_doc_get_num_field(MuMsgDoc* self, MuMsgFieldId mfid) +Mu::mu_msg_doc_get_num_field(MuMsgDoc* self, Field::Id field_id) { g_return_val_if_fail(self, -1); - g_return_val_if_fail(mu_msg_field_id_is_valid(mfid), -1); - g_return_val_if_fail(mu_msg_field_is_numeric(mfid), -1); + g_return_val_if_fail(message_field(field_id).is_numerical(), -1); return xapian_try( [&] { - const std::string s(self->doc().get_value(mfid)); + const auto value_no{message_field(field_id).value_no()}; + const std::string s(self->doc().get_value(value_no)); if (s.empty()) return (gint64)0; - else if (mfid == MU_MSG_FIELD_ID_DATE || mfid == MU_MSG_FIELD_ID_SIZE) + else if (field_id == Field::Id::Date || field_id == Field::Id::Size) return static_cast(strtol(s.c_str(), NULL, 10)); else { return static_cast(Xapian::sortable_unserialise(s)); diff --git a/lib/mu-msg-doc.hh b/lib/mu-msg-doc.hh index b5999b87..afe62a10 100644 --- a/lib/mu-msg-doc.hh +++ b/lib/mu-msg-doc.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2012-2020 Dirk-Jan C. Binnema +** Copyright (C) 2012-2022 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -22,6 +22,7 @@ #include #include +#include "mu-message.hh" namespace Mu { @@ -54,35 +55,35 @@ void mu_msg_doc_destroy(MuMsgDoc* self); * get a string parameter from the msgdoc * * @param self a MuMsgDoc instance - * @param mfid a MuMsgFieldId for a string field + * @param mfid a Message::Field::Id for a string field * * @return a string for the given field (see do_free), or NULL in case of error. * free with g_free */ -gchar* mu_msg_doc_get_str_field(MuMsgDoc* self, MuMsgFieldId mfid) G_GNUC_WARN_UNUSED_RESULT; +gchar* mu_msg_doc_get_str_field(MuMsgDoc* self, Message::Field::Id mfid) G_GNUC_WARN_UNUSED_RESULT; /** * get a string-list parameter from the msgdoc * * @param self a MuMsgDoc instance - * @param mfid a MuMsgFieldId for a string-list field + * @param mfid a Message::Field::Id for a string-list field * * @return a list for the given field (see do_free), or NULL in case * of error. free with mu_str_free_list */ -GSList* mu_msg_doc_get_str_list_field(MuMsgDoc* self, MuMsgFieldId mfid) G_GNUC_WARN_UNUSED_RESULT; +GSList* mu_msg_doc_get_str_list_field(MuMsgDoc* self, Message::Field::Id mfid) G_GNUC_WARN_UNUSED_RESULT; /** * * get a numeric parameter from the msgdoc * * @param self a MuMsgDoc instance - * @param mfid a MuMsgFieldId for a numeric field + * @param mfid a Message::Field::Id for a numeric field * * @return the numerical value, or -1 in case of error. You'll need to - * cast this value to the actual type (e.g. time_t for MU_MSG_FIELD_ID_DATE) + * cast this value to the actual type (e.g. time_t for Field::Id::Date) */ -gint64 mu_msg_doc_get_num_field(MuMsgDoc* self, MuMsgFieldId mfid); +gint64 mu_msg_doc_get_num_field(MuMsgDoc* self, Message::Field::Id mfid); } // namespace Mu diff --git a/lib/mu-msg-fields.c b/lib/mu-msg-fields.c deleted file mode 100644 index daf3c2fe..00000000 --- a/lib/mu-msg-fields.c +++ /dev/null @@ -1,425 +0,0 @@ -/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ - -/* -** Copyright (C) 2008-2017 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#include -#include "mu-msg-fields.h" - -/* - * note: the differences for our purposes between a xapian field and a - * term: - there is only a single value for some item in per document - * (msg), ie. one value containing the list of To: addresses - there - * can be multiple terms, each containing e.g. one of the To: - * addresses - searching uses terms, but to display some field, it - * must be in the value (at least when using MuMsgIter) - */ -enum _FieldFlags { - FLAG_GMIME = 1 << 0, /* field retrieved through - * gmime */ - FLAG_XAPIAN_INDEX = 1 << 1, /* field is indexed in - * xapian (i.e., the text - * is processed */ - FLAG_XAPIAN_TERM = 1 << 2, /* field stored as term in - * xapian (so it can be searched) */ - FLAG_XAPIAN_VALUE = 1 << 3, /* field stored as value in - * xapian (so the literal - * value can be - * retrieved) */ - FLAG_XAPIAN_CONTACT = 1 << 4, /* field contains one or more - * e-mail-addresses */ - FLAG_XAPIAN_BOOLEAN = 1 << 5, /* use 'add_boolean_prefix' - * for Xapian queries; - * wildcards do NOT WORK - * for such fields */ - FLAG_DONT_CACHE = 1 << 6, /* don't cache this field in - * the MuMsg cache */ - FLAG_RANGE_FIELD = 1 << 7 /* whether this is a range field */ - -}; -typedef enum _FieldFlags FieldFlags; - -/* - * this struct describes the fields of an e-mail - /*/ -struct _MuMsgField { - MuMsgFieldId _id; /* the id of the field */ - MuMsgFieldType _type; /* the type of the field */ - const char *_name; /* the name of the field */ - const char _shortcut; /* the shortcut for use in - * --fields and sorting */ - const char _xprefix; /* the Xapian-prefix */ - FieldFlags _flags; /* the flags that tells us - * what to do */ -}; -typedef struct _MuMsgField MuMsgField; - -/* the name and shortcut fields must be lower case, or they might be - * misinterpreted by the query-preprocesser which turns queries into - * lowercase */ -static const MuMsgField FIELD_DATA[] = { - - { - MU_MSG_FIELD_ID_BCC, - MU_MSG_FIELD_TYPE_STRING, - "bcc" , 'h', 'H', /* 'hidden */ - FLAG_GMIME | FLAG_XAPIAN_CONTACT | - FLAG_XAPIAN_VALUE - }, - - { - MU_MSG_FIELD_ID_BODY_TEXT, - MU_MSG_FIELD_TYPE_STRING, - "body", 'b', 'B', - FLAG_GMIME | FLAG_XAPIAN_INDEX | - FLAG_DONT_CACHE - }, - - { - MU_MSG_FIELD_ID_BODY_HTML, - MU_MSG_FIELD_TYPE_STRING, - "bodyhtml", 0, 0, - FLAG_GMIME | FLAG_DONT_CACHE - }, - - { - MU_MSG_FIELD_ID_CC, - MU_MSG_FIELD_TYPE_STRING, - "cc", 'c', 'C', - FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE - }, - - { - MU_MSG_FIELD_ID_DATE, - MU_MSG_FIELD_TYPE_TIME_T, - "date", 'd', 'D', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE | - FLAG_XAPIAN_BOOLEAN | FLAG_RANGE_FIELD - }, - - { - MU_MSG_FIELD_ID_EMBEDDED_TEXT, - MU_MSG_FIELD_TYPE_STRING, - "embed", 'e', 'E', - FLAG_GMIME | FLAG_XAPIAN_INDEX | FLAG_DONT_CACHE - }, - - { - MU_MSG_FIELD_ID_FILE, - MU_MSG_FIELD_TYPE_STRING, - "file" , 'j', 'J', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_DONT_CACHE - }, - - - { - MU_MSG_FIELD_ID_FLAGS, - MU_MSG_FIELD_TYPE_INT, - "flag", 'g', 'G', /* flaGs */ - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - { - MU_MSG_FIELD_ID_FROM, - MU_MSG_FIELD_TYPE_STRING, - "from", 'f', 'F', - FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_MAILDIR, - MU_MSG_FIELD_TYPE_STRING, - "maildir", 'm', 'M', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_MAILING_LIST, - MU_MSG_FIELD_TYPE_STRING, - "list", 'v', 'V', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_MIME, - MU_MSG_FIELD_TYPE_STRING, - "mime" , 'y', 'Y', - FLAG_XAPIAN_TERM - }, - - - { - MU_MSG_FIELD_ID_MSGID, - MU_MSG_FIELD_TYPE_STRING, - "msgid", 'i', 'I', /* 'i' for Id */ - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_PATH, - MU_MSG_FIELD_TYPE_STRING, - "path", 'l', 'L', /* 'l' for location */ - FLAG_GMIME | FLAG_XAPIAN_VALUE | - FLAG_XAPIAN_BOOLEAN - }, - - - { - MU_MSG_FIELD_ID_PRIO, - MU_MSG_FIELD_TYPE_INT, - "prio", 'p', 'P', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_REFS, - MU_MSG_FIELD_TYPE_STRING_LIST, - "refs", 'r', 'R', - FLAG_GMIME | FLAG_XAPIAN_VALUE - }, - - - { - MU_MSG_FIELD_ID_SIZE, - MU_MSG_FIELD_TYPE_BYTESIZE, - "size", 'z', 'Z', /* siZe */ - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE | - FLAG_RANGE_FIELD - }, - - { - MU_MSG_FIELD_ID_SUBJECT, - MU_MSG_FIELD_TYPE_STRING, - "subject", 's', 'S', - FLAG_GMIME | FLAG_XAPIAN_INDEX | FLAG_XAPIAN_VALUE | - FLAG_XAPIAN_TERM - }, - - { - MU_MSG_FIELD_ID_TAGS, - MU_MSG_FIELD_TYPE_STRING_LIST, - "tag", 'x', 'X', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE - }, - - - { /* remember which thread this message is in */ - MU_MSG_FIELD_ID_THREAD_ID, - MU_MSG_FIELD_TYPE_STRING, - "thread", 0, 'W', - FLAG_XAPIAN_TERM - }, - - { - MU_MSG_FIELD_ID_TO, - MU_MSG_FIELD_TYPE_STRING, - "to", 't', 'T', - FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE - }, - - { /* special, internal field, to get a unique key */ - MU_MSG_FIELD_ID_UID, - MU_MSG_FIELD_TYPE_STRING, - "uid", 0, 'U', - FLAG_XAPIAN_TERM - } - - /* note, mu-store also use the 'Q' internal prefix for its uids */ -}; - -/* the MsgField data in an array, indexed by the MsgFieldId; - * this allows for O(1) access - */ -static MuMsgField* _msg_field_data[MU_MSG_FIELD_ID_NUM]; -static const MuMsgField* mu_msg_field (MuMsgFieldId id) -{ - static gboolean _initialized = FALSE; - - /* initialize the array, but only once... */ - if (G_UNLIKELY(!_initialized)) { - int i; - for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) - _msg_field_data[FIELD_DATA[i]._id] = - (MuMsgField*)&FIELD_DATA[i]; - _initialized = TRUE; - } - - return _msg_field_data[id]; -} - - -void -mu_msg_field_foreach (MuMsgFieldForeachFunc func, gconstpointer data) -{ - int i; - for (i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) - func (i, data); -} - - -MuMsgFieldId -mu_msg_field_id_from_name (const char* str, gboolean err) -{ - int i; - - g_return_val_if_fail (str, MU_MSG_FIELD_ID_NONE); - - for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) - if (g_strcmp0(str, FIELD_DATA[i]._name) == 0) - return FIELD_DATA[i]._id; - if (err) - g_return_val_if_reached (MU_MSG_FIELD_ID_NONE); - - return MU_MSG_FIELD_ID_NONE; -} - - -MuMsgFieldId -mu_msg_field_id_from_shortcut (char kar, gboolean err) -{ - int i; - for (i = 0; i != G_N_ELEMENTS(FIELD_DATA); ++i) - if (kar == FIELD_DATA[i]._shortcut) - return FIELD_DATA[i]._id; - - if (err) - g_return_val_if_reached (MU_MSG_FIELD_ID_NONE); - - return MU_MSG_FIELD_ID_NONE; -} - - -gboolean -mu_msg_field_gmime (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_GMIME ? TRUE: FALSE; -} - - -gboolean -mu_msg_field_xapian_index (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & - (FLAG_XAPIAN_INDEX | FLAG_XAPIAN_CONTACT) ? TRUE: FALSE; -} - -gboolean -mu_msg_field_xapian_value (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_XAPIAN_VALUE ? TRUE: FALSE; -} - -gboolean -mu_msg_field_xapian_term (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_XAPIAN_TERM ? TRUE: FALSE; -} - - -gboolean -mu_msg_field_is_range_field (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_RANGE_FIELD ? TRUE: FALSE; -} - - - -gboolean -mu_msg_field_uses_boolean_prefix (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_XAPIAN_BOOLEAN ? TRUE:FALSE; -} - - - -gboolean -mu_msg_field_is_cacheable (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - /* note the FALSE: TRUE */ - return mu_msg_field(id)->_flags & FLAG_DONT_CACHE ? FALSE : TRUE; -} - -gboolean -mu_msg_field_xapian_contact (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),FALSE); - return mu_msg_field(id)->_flags & FLAG_XAPIAN_CONTACT ? TRUE: FALSE; -} - - - -gboolean -mu_msg_field_is_numeric (MuMsgFieldId mfid) -{ - MuMsgFieldType type; - - g_return_val_if_fail (mu_msg_field_id_is_valid(mfid),FALSE); - - type = mu_msg_field_type (mfid); - - return type == MU_MSG_FIELD_TYPE_BYTESIZE || - type == MU_MSG_FIELD_TYPE_TIME_T || - type == MU_MSG_FIELD_TYPE_INT; -} - -const char* -mu_msg_field_name (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),NULL); - return mu_msg_field(id)->_name; -} - - -char -mu_msg_field_shortcut (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),0); - return mu_msg_field(id)->_shortcut; -} - - -char -mu_msg_field_xapian_prefix (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id),0); - return mu_msg_field(id)->_xprefix; -} - - - - -MuMsgFieldType -mu_msg_field_type (MuMsgFieldId id) -{ - g_return_val_if_fail (mu_msg_field_id_is_valid(id), - MU_MSG_FIELD_TYPE_NONE); - return mu_msg_field(id)->_type; -} diff --git a/lib/mu-msg-fields.h b/lib/mu-msg-fields.h deleted file mode 100644 index 08bfe608..00000000 --- a/lib/mu-msg-fields.h +++ /dev/null @@ -1,292 +0,0 @@ -/* -** Copyright (C) 2008-2017 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#ifndef __MU_MSG_FIELDS_H__ -#define __MU_MSG_FIELDS_H__ - -#include - -G_BEGIN_DECLS - -/* don't change the order, add new types at the end, as these numbers - * are used in the database */ -enum _MuMsgFieldId { - - /* first all the string-based ones */ - MU_MSG_FIELD_ID_BCC = 0, - MU_MSG_FIELD_ID_BODY_HTML, - MU_MSG_FIELD_ID_BODY_TEXT, - MU_MSG_FIELD_ID_CC, - MU_MSG_FIELD_ID_EMBEDDED_TEXT, - MU_MSG_FIELD_ID_FILE, - MU_MSG_FIELD_ID_FROM, - MU_MSG_FIELD_ID_MAILDIR, - MU_MSG_FIELD_ID_MIME, /* mime-type */ - MU_MSG_FIELD_ID_MSGID, - MU_MSG_FIELD_ID_PATH, - MU_MSG_FIELD_ID_SUBJECT, - MU_MSG_FIELD_ID_TO, - - MU_MSG_FIELD_ID_UID, /* special, generated from path */ - - /* string list items... */ - MU_MSG_FIELD_ID_REFS, - MU_MSG_FIELD_ID_TAGS, - - /* then the numerical ones */ - MU_MSG_FIELD_ID_DATE, - MU_MSG_FIELD_ID_FLAGS, - MU_MSG_FIELD_ID_PRIO, - MU_MSG_FIELD_ID_SIZE, - - /* add new ones here... */ - MU_MSG_FIELD_ID_MAILING_LIST, /* mailing list */ - MU_MSG_FIELD_ID_THREAD_ID, - - MU_MSG_FIELD_ID_NUM -}; -typedef guint8 MuMsgFieldId; - -/* some specials... */ -static const MuMsgFieldId MU_MSG_FIELD_ID_NONE = (MuMsgFieldId)-1; -#define MU_MSG_STRING_FIELD_ID_NUM (MU_MSG_FIELD_ID_UID + 1) - -/* this is a shortcut for To/From/Cc/Bcc in queries; handled specially - * in mu-query.cc and mu-str.c */ -#define MU_MSG_FIELD_PSEUDO_CONTACT "contact" - -/* this is a shortcut for To/Cc/Bcc in queries; handled specially in - * mu-query.cc and mu-str.c */ -#define MU_MSG_FIELD_PSEUDO_RECIP "recip" - -#define mu_msg_field_id_is_valid(MFID) \ - ((MFID) < MU_MSG_FIELD_ID_NUM) - -/* don't change the order, add new types at the end (before _NUM)*/ -enum _MuMsgFieldType { - MU_MSG_FIELD_TYPE_STRING, - MU_MSG_FIELD_TYPE_STRING_LIST, - - MU_MSG_FIELD_TYPE_BYTESIZE, - MU_MSG_FIELD_TYPE_TIME_T, - MU_MSG_FIELD_TYPE_INT, - - MU_MSG_FIELD_TYPE_NUM -}; -typedef guint8 MuMsgFieldType; -static const MuMsgFieldType MU_MSG_FIELD_TYPE_NONE = (MuMsgFieldType)-1; - -typedef void (*MuMsgFieldForeachFunc) (MuMsgFieldId id, - gconstpointer data); - -/** - * iterator over all possible message fields - * - * @param func a function called for each field - * @param data a user data pointer passed the callback function - */ -void mu_msg_field_foreach (MuMsgFieldForeachFunc func, gconstpointer data); - - -/** - * get the name of the field -- this a name that can be use in queries, - * ie. 'subject:foo', with 'subject' being the name - * - * @param id a MuMsgFieldId - * - * @return the name of the field as a constant string, or - * NULL if the field is unknown - */ -const char* mu_msg_field_name (MuMsgFieldId id) G_GNUC_PURE; - -/** - * get the shortcut of the field -- this a shortcut that can be use in - * queries, ie. 's:foo', with 's' meaning 'subject' being the name - * - * @param id a MuMsgFieldId - * - * @return the shortcut character, or 0 if the field is unknown - */ -char mu_msg_field_shortcut (MuMsgFieldId id) G_GNUC_PURE; - -/** - * get the xapian prefix of the field -- that is, the prefix used in - * the Xapian database to identify the field - * - * @param id a MuMsgFieldId - * - * @return the xapian prefix char or 0 if the field is unknown - */ -char mu_msg_field_xapian_prefix (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * get the type of the field (string, size, time etc.) - * - * @param field a MuMsgField - * - * @return the type of the field (a #MuMsgFieldType), or - * MU_MSG_FIELD_TYPE_NONE if it is not found - */ -MuMsgFieldType mu_msg_field_type (MuMsgFieldId id) G_GNUC_PURE; - - - -/** - * is the field a string? - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field a string, FALSE otherwise - */ -#define mu_msg_field_is_string(MFID)\ - (mu_msg_field_type((MFID))==MU_MSG_FIELD_TYPE_STRING?TRUE:FALSE) - - - -/** - * is the field a string-list? - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field a string-list, FALSE otherwise - */ -#define mu_msg_field_is_string_list(MFID)\ - (mu_msg_field_type((MFID))==MU_MSG_FIELD_TYPE_STRING_LIST?TRUE:FALSE) - -/** - * is the field numeric (has type MU_MSG_FIELD_TYPE_(BYTESIZE|TIME_T|INT))? - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field is numeric, FALSE otherwise - */ -gboolean mu_msg_field_is_numeric (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * whether the field value should be cached (in MuMsg) -- we cache - * values so we can use the MuMsg without needing to keep the - * underlying data source (the GMimeMessage or the database ptr) alive - * in practice, the fields we *don't* cache are the message body - * (html, txt), because they take too much memory - */ -gboolean mu_msg_field_is_cacheable (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * is the field Xapian-indexable? That is, should this field be - * indexed in the Xapian database, so we can use the all the - * phrasing, stemming etc. magic - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field is Xapian-enabled, FALSE otherwise - */ -gboolean mu_msg_field_xapian_index (MuMsgFieldId id) G_GNUC_PURE; - -/** - * should this field be stored as a xapian term? - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field is Xapian-enabled, FALSE otherwise - */ -gboolean mu_msg_field_xapian_term (MuMsgFieldId id) G_GNUC_PURE; - -/** - * should this field be stored as a xapian value? - * - * @param field a MuMsgField - * - * @return TRUE if the field is Xapian-enabled, FALSE otherwise - */ -gboolean mu_msg_field_xapian_value (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * whether we should use add_boolean_prefix (see Xapian documentation) - * for this field in queries. Used in mu-query.cc - * - * @param id a MuMsgFieldId - * - * @return TRUE if this field wants add_boolean_prefix, FALSE - * otherwise - */ -gboolean mu_msg_field_uses_boolean_prefix (MuMsgFieldId id) G_GNUC_PURE; - -/** - * is this a range-field? ie. date, or size - * - * @param id a MuMsgField - * - * @return TRUE if this field is a range field, FALSE otherwise - */ -gboolean mu_msg_field_is_range_field (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * should this field be stored as contact information? This means that - * e-mail address will be stored as terms, and names will be indexed - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field should be stored as contact information, - * FALSE otherwise - */ -gboolean mu_msg_field_xapian_contact (MuMsgFieldId id) G_GNUC_PURE; - -/** - * is the field gmime-enabled? That is, can be field be retrieved - * using GMime? - * - * @param id a MuMsgFieldId - * - * @return TRUE if the field is Gmime-enabled, FALSE otherwise - */ -gboolean mu_msg_field_gmime (MuMsgFieldId id) G_GNUC_PURE; - - -/** - * get the corresponding MuMsgField for a name (as in mu_msg_field_name) - * - * @param str a name - * @param err, if TRUE, when the shortcut is not found, will issue a - * g_critical warning - * - * @return a MuMsgField, or NULL if it could not be found - */ -MuMsgFieldId mu_msg_field_id_from_name (const char* str, - gboolean err) G_GNUC_PURE; - - -/** - * get the corresponding MuMsgField for a shortcut (as in mu_msg_field_shortcut) - * - * @param kar a shortcut character - * @param err, if TRUE, when the shortcut is not found, will issue a - * g_critical warning - * - * @return a MuMsgField, or NULL if it could not be found - */ -MuMsgFieldId mu_msg_field_id_from_shortcut (char kar, - gboolean err) G_GNUC_PURE; -G_END_DECLS - -#endif /*__MU_MSG_FIELDS_H__*/ diff --git a/lib/mu-msg-file.cc b/lib/mu-msg-file.cc index a04b6d3c..608657f3 100644 --- a/lib/mu-msg-file.cc +++ b/lib/mu-msg-file.cc @@ -33,9 +33,11 @@ #include "mu-msg-priv.hh" #include "utils/mu-util.h" +#include "utils/mu-utils.hh" #include "utils/mu-str.h" using namespace Mu; +using namespace Mu::Message; static gboolean init_file_metadata(MuMsgFile* self, const char* path, const char* mdir, GError** err); @@ -85,19 +87,19 @@ init_file_metadata(MuMsgFile* self, const char* path, const gchar* mdir, GError* if (access(path, R_OK) != 0) { mu_util_g_set_error(err, - MU_ERROR_FILE, - "cannot read file %s: %s", - path, - g_strerror(errno)); + MU_ERROR_FILE, + "cannot read file %s: %s", + path, + g_strerror(errno)); return FALSE; } if (stat(path, &statbuf) < 0) { mu_util_g_set_error(err, - MU_ERROR_FILE, - "cannot stat %s: %s", - path, - g_strerror(errno)); + MU_ERROR_FILE, + "cannot stat %s: %s", + path, + g_strerror(errno)); return FALSE; } @@ -147,21 +149,21 @@ get_mime_stream(MuMsgFile* self, const char* path, GError** err) file = fopen(path, "r"); if (!file) { g_set_error(err, - MU_ERROR_DOMAIN, - MU_ERROR_FILE, - "cannot open %s: %s", - path, - g_strerror(errno)); + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "cannot open %s: %s", + path, + g_strerror(errno)); return NULL; } stream = g_mime_stream_file_new(file); if (!stream) { g_set_error(err, - MU_ERROR_DOMAIN, - MU_ERROR_GMIME, - "cannot create mime stream for %s", - path); + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "cannot create mime stream for %s", + path); fclose(file); return NULL; } @@ -170,10 +172,10 @@ get_mime_stream(MuMsgFile* self, const char* path, GError** err) if (!self->_sha1) { ::fclose(file); g_set_error(err, - MU_ERROR_DOMAIN, - MU_ERROR_FILE, - "failed to get sha-1 for %s", - path); + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "failed to get sha-1 for %s", + path); return NULL; } @@ -194,10 +196,10 @@ init_mime_msg(MuMsgFile* self, const char* path, GError** err) g_object_unref(stream); if (!parser) { g_set_error(err, - MU_ERROR_DOMAIN, - MU_ERROR_GMIME, - "cannot create mime parser for %s", - path); + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "cannot create mime parser for %s", + path); return FALSE; } @@ -205,10 +207,10 @@ init_mime_msg(MuMsgFile* self, const char* path, GError** err) g_object_unref(parser); if (!self->_mime_msg) { g_set_error(err, - MU_ERROR_DOMAIN, - MU_ERROR_GMIME, - "message seems invalid, ignoring (%s)", - path); + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "message seems invalid, ignoring (%s)", + path); return FALSE; } @@ -307,9 +309,9 @@ looks_like_attachment(GMimeObject* part) const char* type; const char* sub_type; } att_types[] = {{"image", "*"}, - {"audio", "*"}, - {"application", "*"}, - {"application", "x-patch"}}; + {"audio", "*"}, + {"application", "*"}, + {"application", "x-patch"}}; disp = g_mime_object_get_content_disposition(part); @@ -392,9 +394,9 @@ get_content_flags(MuMsgFile* self) msg_cflags_cb(NULL, GMIME_OBJECT(self->_mime_msg), &flags); /* parts */ mu_mime_message_foreach(self->_mime_msg, - FALSE, /* never decrypt for this */ - (GMimeObjectForeachFunc)msg_cflags_cb, - &flags); + FALSE, /* never decrypt for this */ + (GMimeObjectForeachFunc)msg_cflags_cb, + &flags); } char *ml{get_mailing_list(self)}; @@ -439,17 +441,17 @@ parse_prio_str(const char* priostr) const char* _str; MessagePriority _prio; } str_prio[] = {{"high", MessagePriority::High}, - {"1", MessagePriority::High}, - {"2", MessagePriority::High}, + {"1", MessagePriority::High}, + {"2", MessagePriority::High}, - {"normal", MessagePriority::Normal}, - {"3", MessagePriority::Normal}, + {"normal", MessagePriority::Normal}, + {"3", MessagePriority::Normal}, - {"low", MessagePriority::Low}, - {"list", MessagePriority::Low}, - {"bulk", MessagePriority::Low}, - {"4", MessagePriority::Low}, - {"5", MessagePriority::Low}}; + {"low", MessagePriority::Low}, + {"list", MessagePriority::Low}, + {"bulk", MessagePriority::Low}, + {"4", MessagePriority::Low}, + {"5", MessagePriority::Low}}; for (i = 0; i != G_N_ELEMENTS(str_prio); ++i) if (g_ascii_strcasecmp(priostr, str_prio[i]._str) == 0) @@ -682,13 +684,13 @@ cleanup_maybe(const char* str, gboolean* do_free) } G_GNUC_CONST static GMimeAddressType -address_type(MuMsgFieldId mfid) +address_type(Field::Id field_id) { - switch (mfid) { - case MU_MSG_FIELD_ID_BCC: return GMIME_ADDRESS_TYPE_BCC; - case MU_MSG_FIELD_ID_CC: return GMIME_ADDRESS_TYPE_CC; - case MU_MSG_FIELD_ID_TO: return GMIME_ADDRESS_TYPE_TO; - case MU_MSG_FIELD_ID_FROM: return GMIME_ADDRESS_TYPE_FROM; + switch (field_id) { + case Field::Id::Bcc: return GMIME_ADDRESS_TYPE_BCC; + case Field::Id::Cc: return GMIME_ADDRESS_TYPE_CC; + case Field::Id::To: return GMIME_ADDRESS_TYPE_TO; + case Field::Id::From: return GMIME_ADDRESS_TYPE_FROM; default: g_return_val_if_reached((GMimeAddressType)-1); } } @@ -708,34 +710,35 @@ get_msgid(MuMsgFile* self, gboolean* do_free) } char* -Mu::mu_msg_file_get_str_field(MuMsgFile* self, MuMsgFieldId mfid, gboolean* do_free) +Mu::mu_msg_file_get_str_field(MuMsgFile* self, Field::Id field_id, gboolean* do_free) { g_return_val_if_fail(self, NULL); - g_return_val_if_fail(mu_msg_field_is_string(mfid), NULL); + g_return_val_if_fail(message_field(field_id).is_string(), NULL); *do_free = FALSE; /* default */ - switch (mfid) { - case MU_MSG_FIELD_ID_BCC: - case MU_MSG_FIELD_ID_CC: - case MU_MSG_FIELD_ID_FROM: - case MU_MSG_FIELD_ID_TO: *do_free = TRUE; return get_recipient(self, address_type(mfid)); + switch (field_id) { + case Field::Id::Bcc: + case Field::Id::Cc: + case Field::Id::From: + case Field::Id::To: *do_free = TRUE; return get_recipient(self, address_type(field_id)); - case MU_MSG_FIELD_ID_PATH: return self->_path; + case Field::Id::Path: return self->_path; - case MU_MSG_FIELD_ID_MAILING_LIST: *do_free = TRUE; return (char*)get_mailing_list(self); + case Field::Id::MailingList: *do_free = TRUE; return (char*)get_mailing_list(self); - case MU_MSG_FIELD_ID_SUBJECT: + case Field::Id::Subject: return (char*)cleanup_maybe(g_mime_message_get_subject(self->_mime_msg), do_free); - case MU_MSG_FIELD_ID_MSGID: return get_msgid(self, do_free); + case Field::Id::MessageId: return get_msgid(self, do_free); - case MU_MSG_FIELD_ID_MAILDIR: return self->_maildir; + case Field::Id::Maildir: return self->_maildir; - case MU_MSG_FIELD_ID_BODY_TEXT: /* use mu_msg_get_body_text */ - case MU_MSG_FIELD_ID_BODY_HTML: /* use mu_msg_get_body_html */ - case MU_MSG_FIELD_ID_EMBEDDED_TEXT: - g_warning("%s is not retrievable through: %s", mu_msg_field_name(mfid), __func__); + case Field::Id::BodyText: /* use mu_msg_get_body_text */ + case Field::Id::BodyHtml: /* use mu_msg_get_body_html */ + case Field::Id::EmbeddedText: + g_warning("%*s is not retrievable through: %s", + STR_V(message_field(field_id).name), __func__); return NULL; default: g_return_val_if_reached(NULL); @@ -743,36 +746,36 @@ Mu::mu_msg_file_get_str_field(MuMsgFile* self, MuMsgFieldId mfid, gboolean* do_f } GSList* -Mu::mu_msg_file_get_str_list_field(MuMsgFile* self, MuMsgFieldId mfid) +Mu::mu_msg_file_get_str_list_field(MuMsgFile* self, Field::Id field_id) { g_return_val_if_fail(self, NULL); - g_return_val_if_fail(mu_msg_field_is_string_list(mfid), NULL); + g_return_val_if_fail(message_field(field_id).is_string_list(), NULL); - switch (mfid) { - case MU_MSG_FIELD_ID_REFS: return get_references(self); - case MU_MSG_FIELD_ID_TAGS: return get_tags(self); + switch (field_id) { + case Field::Id::References: return get_references(self); + case Field::Id::Tags: return get_tags(self); default: g_return_val_if_reached(NULL); } } gint64 -Mu::mu_msg_file_get_num_field(MuMsgFile* self, const MuMsgFieldId mfid) +Mu::mu_msg_file_get_num_field(MuMsgFile* self, const Field::Id field_id) { g_return_val_if_fail(self, -1); - g_return_val_if_fail(mu_msg_field_is_numeric(mfid), -1); + g_return_val_if_fail(message_field(field_id).is_numerical(), -1); - switch (mfid) { - case MU_MSG_FIELD_ID_DATE: { + switch (field_id) { + case Field::Id::Date: { GDateTime* dt; dt = g_mime_message_get_date(self->_mime_msg); return dt ? g_date_time_to_unix(dt) : 0; } - case MU_MSG_FIELD_ID_FLAGS: return (gint64)get_flags(self); + case Field::Id::Flags: return (gint64)get_flags(self); - case MU_MSG_FIELD_ID_PRIO: return (gint64)get_prio(self); + case Field::Id::Priority: return (gint64)get_prio(self); - case MU_MSG_FIELD_ID_SIZE: return (gint64)get_size(self); + case Field::Id::Size: return (gint64)get_size(self); default: g_return_val_if_reached(-1); } @@ -811,17 +814,17 @@ foreach_cb(GMimeObject* parent, GMimeObject* part, ForeachData* fdata) if (fdata->decrypt && GMIME_IS_MULTIPART_ENCRYPTED(part)) { GMimeObject* dec; dec = mu_msg_crypto_decrypt_part(GMIME_MULTIPART_ENCRYPTED(part), - MU_MSG_OPTION_NONE, - NULL, - NULL, - NULL); + MU_MSG_OPTION_NONE, + NULL, + NULL, + NULL); if (!dec) return; if (GMIME_IS_MULTIPART(dec)) g_mime_multipart_foreach((GMIME_MULTIPART(dec)), - (GMimeObjectForeachFunc)foreach_cb, - fdata); + (GMimeObjectForeachFunc)foreach_cb, + fdata); else foreach_cb(parent, dec, fdata); @@ -831,9 +834,9 @@ foreach_cb(GMimeObject* parent, GMimeObject* part, ForeachData* fdata) void Mu::mu_mime_message_foreach(GMimeMessage* msg, - gboolean decrypt, - GMimeObjectForeachFunc func, - gpointer user_data) + gboolean decrypt, + GMimeObjectForeachFunc func, + gpointer user_data) { ForeachData fdata; diff --git a/lib/mu-msg-file.hh b/lib/mu-msg-file.hh index 953ef41f..b8be4309 100644 --- a/lib/mu-msg-file.hh +++ b/lib/mu-msg-file.hh @@ -20,6 +20,8 @@ #ifndef MU_MSG_FILE_HH__ #define MU_MSG_FILE_HH__ +#include "mu-message.hh" + namespace Mu { struct MuMsgFile; @@ -34,8 +36,8 @@ struct MuMsgFile; * @return a new MuMsg, or NULL in case of error */ MuMsgFile* mu_msg_file_new(const char* path, - const char* mdir, - GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + const char* mdir, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * destroy a MuMsgFile object @@ -68,8 +70,8 @@ char* mu_msg_file_get_header(MuMsgFile* self, const char* header); * @return a string, or NULL */ char* mu_msg_file_get_str_field(MuMsgFile* self, - MuMsgFieldId msfid, - gboolean* do_free) G_GNUC_WARN_UNUSED_RESULT; + Message::Field::Id msfid, + gboolean* do_free) G_GNUC_WARN_UNUSED_RESULT; /** * get a string-list value for this message @@ -80,7 +82,7 @@ char* mu_msg_file_get_str_field(MuMsgFile* self, * @return a GSList*, or NULL; free with mu_str_free_list */ GSList* mu_msg_file_get_str_list_field(MuMsgFile* self, - MuMsgFieldId msfid) G_GNUC_WARN_UNUSED_RESULT; + Message::Field::Id msfid) G_GNUC_WARN_UNUSED_RESULT; /** * get a numeric value for this message -- the return value should be @@ -91,7 +93,7 @@ GSList* mu_msg_file_get_str_list_field(MuMsgFile* self, * * @return the numeric value, or -1 in case of error */ -gint64 mu_msg_file_get_num_field(MuMsgFile* self, MuMsgFieldId mfid); +gint64 mu_msg_file_get_num_field(MuMsgFile* self, Message::Field::Id mfid); } // namespace Mu diff --git a/lib/mu-msg.cc b/lib/mu-msg.cc index bbb6e3d0..1dded768 100644 --- a/lib/mu-msg.cc +++ b/lib/mu-msg.cc @@ -40,6 +40,7 @@ #include "mu-maildir.hh" using namespace Mu; +using namespace Mu::Message; /* note, we do the gmime initialization here rather than in * mu-runtime, because this way we don't need mu-runtime for simple @@ -101,8 +102,8 @@ Mu::mu_msg_new_from_file(const char* path, const char* mdir, GError** err) self->_file = msgfile; g_debug("created message from %s in %" G_GINT64_FORMAT " μs", - path, - g_get_monotonic_time() - start); + path, + g_get_monotonic_time() - start); return self; } @@ -197,12 +198,12 @@ get_path(MuMsg* self) val = NULL; if (self->_doc) - val = mu_msg_doc_get_str_field(self->_doc, MU_MSG_FIELD_ID_PATH); + val = mu_msg_doc_get_str_field(self->_doc, Field::Id::Path); /* not in the cache yet? try to get it from the file backend, * in case we are using that */ if (!val && self->_file) - val = mu_msg_file_get_str_field(self->_file, MU_MSG_FIELD_ID_PATH, &do_free); + val = mu_msg_file_get_str_field(self->_file, Field::Id::Path, &do_free); /* shouldn't happen */ if (!val) @@ -242,27 +243,28 @@ Mu::mu_msg_unload_msg_file(MuMsg* msg) } static const GSList* -get_str_list_field(MuMsg* self, MuMsgFieldId mfid) +get_str_list_field(MuMsg* self, Field::Id field_id) { GSList* val; val = NULL; - if (self->_doc && mu_msg_field_xapian_value(mfid)) - val = mu_msg_doc_get_str_list_field(self->_doc, mfid); - else if (mu_msg_field_gmime(mfid)) { + if (self->_doc && + any_of(message_field(field_id).flags & Field::Flag::Value)) + val = mu_msg_doc_get_str_list_field(self->_doc, field_id); + else if (any_of(message_field(field_id).flags & Field::Flag::GMime)) { /* if we don't have a file object yet, we need to * create it from the file on disk */ if (!mu_msg_load_msg_file(self, NULL)) return NULL; - val = mu_msg_file_get_str_list_field(self->_file, mfid); + val = mu_msg_file_get_str_list_field(self->_file, field_id); } return free_later_lst(self, val); } static const char* -get_str_field(MuMsg* self, MuMsgFieldId mfid) +get_str_field(MuMsg* self, Field::Id field_id) { char* val; gboolean do_free; @@ -270,15 +272,16 @@ get_str_field(MuMsg* self, MuMsgFieldId mfid) do_free = TRUE; val = NULL; - if (self->_doc && mu_msg_field_xapian_value(mfid)) - val = mu_msg_doc_get_str_field(self->_doc, mfid); + if (self->_doc && + any_of(message_field(field_id).flags & Field::Flag::Value)) + val = mu_msg_doc_get_str_field(self->_doc, field_id); - else if (mu_msg_field_gmime(mfid)) { + else if (any_of(message_field(field_id).flags & Field::Flag::GMime)) { /* if we don't have a file object yet, we need to * create it from the file on disk */ if (!mu_msg_load_msg_file(self, NULL)) return NULL; - val = mu_msg_file_get_str_field(self->_file, mfid, &do_free); + val = mu_msg_file_get_str_field(self->_file, field_id, &do_free); } else val = NULL; @@ -286,17 +289,18 @@ get_str_field(MuMsg* self, MuMsgFieldId mfid) } static gint64 -get_num_field(MuMsg* self, MuMsgFieldId mfid) +get_num_field(MuMsg* self, Field::Id field_id) { - if (self->_doc && mu_msg_field_xapian_value(mfid)) - return mu_msg_doc_get_num_field(self->_doc, mfid); + if (self->_doc && + any_of(message_field(field_id).flags & Field::Flag::Value)) + return mu_msg_doc_get_num_field(self->_doc, field_id); /* if we don't have a file object yet, we need to * create it from the file on disk */ if (!mu_msg_load_msg_file(self, NULL)) return -1; - return mu_msg_file_get_num_field(self->_file, mfid); + return mu_msg_file_get_num_field(self->_file, field_id); } const char* @@ -312,7 +316,7 @@ Mu::mu_msg_get_header(MuMsg* self, const char* header) err = NULL; if (!mu_msg_load_msg_file(self, &err)) { g_warning("failed to load message file: %s", - err ? err->message : "something went wrong"); + err ? err->message : "something went wrong"); return NULL; } @@ -341,21 +345,21 @@ const char* Mu::mu_msg_get_path(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_PATH); + return get_str_field(self, Field::Id::Path); } const char* Mu::mu_msg_get_subject(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_SUBJECT); + return get_str_field(self, Field::Id::Subject); } const char* Mu::mu_msg_get_msgid(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_MSGID); + return get_str_field(self, Field::Id::MessageId); } const char* @@ -366,7 +370,7 @@ Mu::mu_msg_get_mailing_list(MuMsg* self) g_return_val_if_fail(self, NULL); - ml = get_str_field(self, MU_MSG_FIELD_ID_MAILING_LIST); + ml = get_str_field(self, Field::Id::MailingList); if (!ml) return NULL; @@ -381,56 +385,56 @@ const char* Mu::mu_msg_get_maildir(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_MAILDIR); + return get_str_field(self, Field::Id::Maildir); } const char* Mu::mu_msg_get_from(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_FROM); + return get_str_field(self, Field::Id::From); } const char* Mu::mu_msg_get_to(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_TO); + return get_str_field(self, Field::Id::To); } const char* Mu::mu_msg_get_cc(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_CC); + return get_str_field(self, Field::Id::Cc); } const char* Mu::mu_msg_get_bcc(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_field(self, MU_MSG_FIELD_ID_BCC); + return get_str_field(self, Field::Id::Bcc); } time_t Mu::mu_msg_get_date(MuMsg* self) { g_return_val_if_fail(self, (time_t)-1); - return (time_t)get_num_field(self, MU_MSG_FIELD_ID_DATE); + return (time_t)get_num_field(self, Field::Id::Date); } MessageFlags Mu::mu_msg_get_flags(MuMsg* self) { g_return_val_if_fail(self, MessageFlags::None); - return static_cast(get_num_field(self, MU_MSG_FIELD_ID_FLAGS)); + return static_cast(get_num_field(self, Field::Id::Flags)); } size_t Mu::mu_msg_get_size(MuMsg* self) { g_return_val_if_fail(self, (size_t)-1); - return (size_t)get_num_field(self, MU_MSG_FIELD_ID_SIZE); + return (size_t)get_num_field(self, Field::Id::Size); } Mu::MessagePriority @@ -439,7 +443,7 @@ Mu::mu_msg_get_prio(MuMsg* self) g_return_val_if_fail(self, MessagePriority{}); return message_priority_from_char( - static_cast(get_num_field(self, MU_MSG_FIELD_ID_PRIO))); + static_cast(get_num_field(self, Field::Id::Priority))); } struct _BodyData { @@ -514,7 +518,7 @@ find_content_type(MuMsg* msg, MuMsgPart* mpart, ContentTypeData* cdata) if (!cdata->want_html && (mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN)) wanted = (GMimePart*)mpart->data; else if (!(mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && cdata->want_html && - (mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML)) + (mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML)) wanted = (GMimePart*)mpart->data; else wanted = NULL; @@ -583,35 +587,35 @@ const GSList* Mu::mu_msg_get_references(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_list_field(self, MU_MSG_FIELD_ID_REFS); + return get_str_list_field(self, Field::Id::References); } const GSList* Mu::mu_msg_get_tags(MuMsg* self) { g_return_val_if_fail(self, NULL); - return get_str_list_field(self, MU_MSG_FIELD_ID_TAGS); + return get_str_list_field(self, Field::Id::Tags); } const char* -Mu::mu_msg_get_field_string(MuMsg* self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_string(MuMsg* self, Field::Id field_id) { g_return_val_if_fail(self, NULL); - return get_str_field(self, mfid); + return get_str_field(self, field_id); } const GSList* -Mu::mu_msg_get_field_string_list(MuMsg* self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_string_list(MuMsg* self, Field::Id field_id) { g_return_val_if_fail(self, NULL); - return get_str_list_field(self, mfid); + return get_str_list_field(self, field_id); } gint64 -Mu::mu_msg_get_field_numeric(MuMsg* self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_numeric(MuMsg* self, Field::Id field_id) { g_return_val_if_fail(self, -1); - return get_num_field(self, mfid); + return get_num_field(self, field_id); } @@ -624,14 +628,14 @@ get_all_contacts(MuMsg *self) MessageContact::Type::Cc, MessageContact::Type::ReplyTo, MessageContact::Type::Bcc}) { auto type_contacts{mu_msg_get_contacts(self, mtype)}; - + contacts.reserve(contacts.size() + type_contacts.size()); contacts.insert(contacts.end(), type_contacts.begin(), type_contacts.end()); } return contacts; } - + Mu::MessageContacts Mu::mu_msg_get_contacts(MuMsg *self, MessageContact::Type mtype) { @@ -642,7 +646,7 @@ Mu::mu_msg_get_contacts(MuMsg *self, MessageContact::Type mtype) if (mtype == MessageContact::Type::Unknown) return get_all_contacts(self); - + const auto info = std::invoke([&]()->AddressInfo { switch (mtype) { case MessageContact::Type::From: @@ -666,12 +670,12 @@ Mu::mu_msg_get_contacts(MuMsg *self, MessageContact::Type mtype) self->_file->_mime_msg, info.first)}; lst) return make_message_contacts(lst, mtype, mdate); } else if (info.second) { - if (auto&& lst_str{info.second(self)}; lst_str) + if (auto&& lst_str{info.second(self)}; lst_str) return make_message_contacts(lst_str, mtype, mdate); } - + return {}; - + } @@ -692,11 +696,11 @@ Mu::mu_msg_is_readable(MuMsg* self) bool Mu::mu_msg_move_to_maildir(MuMsg* self, const std::string& root_maildir_path, - const std::string& target_maildir, + const std::string& target_maildir, MessageFlags flags, - bool ignore_dups, - bool new_name, - GError** err) + bool ignore_dups, + bool new_name, + GError** err) { g_return_val_if_fail(self, false); @@ -763,7 +767,7 @@ Mu::mu_str_display_contact_s(const char* str) for (c2 = contact; c2 < c && !(isalnum(*c2)); ++c2) ; if (c2 != c) /* apparently, there was something, - * so we can remove the <... part*/ + * so we can remove the <... part*/ *c = '\0'; } diff --git a/lib/mu-msg.hh b/lib/mu-msg.hh index 2e1262f1..8dbf2383 100644 --- a/lib/mu-msg.hh +++ b/lib/mu-msg.hh @@ -22,11 +22,8 @@ #include -#include -#include -#include +#include -#include #include #include #include @@ -83,8 +80,8 @@ MU_ENABLE_BITOPS(MuMsgOptions); * mu_msg_unref when done with this message */ MuMsg* mu_msg_new_from_file(const char* filepath, - const char* maildir, - GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + const char* maildir, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * create a new MuMsg* instance based on a Xapian::Document @@ -100,7 +97,7 @@ MuMsg* mu_msg_new_from_file(const char* filepath, * mu_msg_unref when done with this message */ MuMsg* mu_msg_new_from_doc(XapianDocument* doc, - GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * if we don't have a message file yet (because this message is @@ -320,7 +317,7 @@ size_t mu_msg_get_size(MuMsg* msg); * * @return a string that should not be freed */ -const char* mu_msg_get_field_string(MuMsg* msg, MuMsgFieldId mfid); +const char* mu_msg_get_field_string(MuMsg* msg, Message::Field::Id mfid); /** * get some field value as string-list @@ -330,7 +327,7 @@ const char* mu_msg_get_field_string(MuMsg* msg, MuMsgFieldId mfid); * * @return a list that should not be freed */ -const GSList* mu_msg_get_field_string_list(MuMsg* self, MuMsgFieldId mfid); +const GSList* mu_msg_get_field_string_list(MuMsg* self, Message::Field::Id mfid); /** * get some field value as string @@ -340,7 +337,7 @@ const GSList* mu_msg_get_field_string_list(MuMsg* self, MuMsgFieldId mfid); * * @return a string that should not be freed */ -gint64 mu_msg_get_field_numeric(MuMsg* msg, MuMsgFieldId mfid); +gint64 mu_msg_get_field_numeric(MuMsg* msg, Message::Field::Id mfid); /** * get the message priority for this message. The X-Priority, X-MSMailPriority, @@ -404,7 +401,7 @@ const GSList* mu_msg_get_tags(MuMsg* self); * @return negative if m1 is smaller, positive if m1 is smaller, 0 if * they are equal */ -int mu_msg_cmp(MuMsg* m1, MuMsg* m2, MuMsgFieldId mfid); +int mu_msg_cmp(MuMsg* m1, MuMsg* m2, Message::Field::Id mfid); /** * check whether there there's a readable file behind this message @@ -440,17 +437,17 @@ bool mu_msg_move_to_maildir(MuMsg* msg, bool ignore_dups, bool new_name, GError** err); -/** +/** * Get a sequence with contacts of the given type for this message. * * @param msg a valid MuMsg* instance * @param mtype the contact type; with Type::Unknown, get _all_ types. - * + * * @return a sequence */ Mu::MessageContacts mu_msg_get_contacts (MuMsg *self, MessageContact::Type mtype=MessageContact::Type::Unknown); - + /** * create a 'display contact' from an email header To/Cc/Bcc/From-type address * ie., turn @@ -489,7 +486,7 @@ struct QueryMatch; * - MU_MSG_OPTION_EXTRACT_IMAGES: extract image attachments as temporary * files and include links to those in the sexp * and for message parts: - * MU_MSG_OPTION_CHECK_SIGNATURES: check signatures + * MU_MSG_OPTION_CHECK_SIGNATURES: check signatures * MU_MSG_OPTION_AUTO_RETRIEVE_KEY: attempt to retrieve keys online * MU_MSG_OPTION_USE_AGENT: attempt to use GPG-agent * MU_MSG_OPTION_USE_PKCS7: attempt to use PKCS (instead of gpg)