diff --git a/.clang-format b/.clang-format index 621eb83f..91769fe3 100644 --- a/.clang-format +++ b/.clang-format @@ -1,20 +1,20 @@ --- AlignAfterOpenBracket: 'Align' -AlignConsecutiveAssignments: 'false' -AlignConsecutiveDeclarations: 'false' +AlignConsecutiveAssignments: 'true' +AlignConsecutiveDeclarations: 'true' AlignConsecutiveMacros: 'true' AlignOperands: 'true' AlignTrailingComments: 'true' AllowAllArgumentsOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortBlocksOnASingleLine: 'false' -AllowShortCaseLabelsOnASingleLine: 'false' +AllowShortCaseLabelsOnASingleLine: 'true' AllowShortFunctionsOnASingleLine: 'Inline' AllowShortIfStatementsOnASingleLine: 'false' -AlwaysBreakAfterReturnType: 'All' -BinPackParameters: 'false' +AlwaysBreakAfterReturnType: 'TopLevelDefinitions' BinPackArguments: 'false' -BreakBeforeBraces: 'Linux' +BinPackParameters: 'false' +BreakBeforeBraces: 'WebKit' ColumnLimit: '100' DerivePointerAlignment: 'false' IndentCaseLabels: 'false' @@ -22,7 +22,9 @@ IndentWidth: '8' KeepEmptyLinesAtTheStartOfBlocks: 'false' Language: 'Cpp' MaxEmptyLinesToKeep: '1' -PointerAlignment: 'Right' +PenaltyBreakAssignment: '3' +PenaltyBreakBeforeFirstCallParameter: '15' +PointerAlignment: 'Left' SortIncludes: 'false' SpaceAfterCStyleCast: 'false' SpaceBeforeAssignmentOperators : 'true' @@ -31,8 +33,6 @@ SpaceInEmptyParentheses: 'false' SpacesInSquareBrackets: 'false' TabWidth: '8' UseTab: 'AlignWithSpaces' -PenaltyBreakAssignment: '3' -PenaltyBreakBeforeFirstCallParameter: '15' # Local Variables: # mode: yaml diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 0793144b..e1b7f112 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -30,7 +30,7 @@ jobs: brew install meson ninja libgpg-error libtool pkg-config glib gmime xapian - name: configure - run: ./autogen.sh --disable-guile + run: ./autogen.sh -Dguile=disabled - name: build run: make diff --git a/Makefile.meson b/Makefile.meson index 8427a1b2..7e069b88 100644 --- a/Makefile.meson +++ b/Makefile.meson @@ -31,6 +31,9 @@ check: test test: $(BUILDDIR) @cd $(BUILDDIR); $(MESON) test +test-valgrind: $(BUILDDIR) + @cd $(BUILDDIR); $(MESON) test --wrap='valgrind --leak-check=full --error-exitcode=1' + dist: $(BUILDDIR) @cd $(BUILDDIR); $(MESON) dist diff --git a/autogen.sh b/autogen.sh index d674afb3..eac4d6b7 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,7 +18,7 @@ fi # we could remove build/ but let's avoid rm -rf risks... if test -d ${BUILDDIR}; then - meson --reconfigure ${BUILDDIR} + meson --reconfigure ${BUILDDIR} $@ else meson ${BUILDDIR} $@ fi diff --git a/configure.ac b/configure.ac index 1c0e82e0..8a81e76f 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. AC_PREREQ([2.68]) -AC_INIT([mu],[1.7.0],[https://github.com/djcb/mu/issues],[mu]) +AC_INIT([mu],[1.7.3],[https://github.com/djcb/mu/issues],[mu]) AC_COPYRIGHT([Copyright (C) 2008-2021 Dirk-Jan C. Binnema]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([mu/mu.cc]) @@ -97,7 +97,7 @@ AS_IF([test "x$enable_mu4e" != "xno"], [ ]) AS_CASE([$emacs_version], [*25.3*],[build_mu4e=yes], - [*26*|*27*|*28*],[build_mu4e=yes], + [*26*|*27*|*28*|*29*],[build_mu4e=yes], [AC_WARN([emacs is too old to build mu4e (need emacs >= 25.3)])]) ]) AM_CONDITIONAL(BUILD_MU4E, test "x$build_mu4e" = "xyes") diff --git a/guile/mu-guile-message.cc b/guile/mu-guile-message.cc index 0cb1dd07..034a18ae 100644 --- a/guile/mu-guile-message.cc +++ b/guile/mu-guile-message.cc @@ -40,60 +40,57 @@ using namespace Mu; /* some symbols */ static SCM SYMB_PRIO_LOW, SYMB_PRIO_NORMAL, SYMB_PRIO_HIGH; -static SCM SYMB_FLAG_NEW, SYMB_FLAG_PASSED, SYMB_FLAG_REPLIED, - SYMB_FLAG_SEEN, SYMB_FLAG_TRASHED, SYMB_FLAG_DRAFT, - SYMB_FLAG_FLAGGED, SYMB_FLAG_SIGNED, SYMB_FLAG_ENCRYPTED, - SYMB_FLAG_HAS_ATTACH, SYMB_FLAG_UNREAD, SYMB_FLAG_LIST; -static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, - SYMB_CONTACT_FROM; +static SCM SYMB_FLAG_NEW, SYMB_FLAG_PASSED, SYMB_FLAG_REPLIED, SYMB_FLAG_SEEN, SYMB_FLAG_TRASHED, + SYMB_FLAG_DRAFT, SYMB_FLAG_FLAGGED, SYMB_FLAG_SIGNED, SYMB_FLAG_ENCRYPTED, SYMB_FLAG_HAS_ATTACH, + SYMB_FLAG_UNREAD, SYMB_FLAG_LIST; +static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, SYMB_CONTACT_FROM; struct _MuMsgWrapper { - MuMsg *_msg; + MuMsg* _msg; gboolean _unrefme; }; typedef struct _MuMsgWrapper MuMsgWrapper; -static long MSG_TAG; +static long MSG_TAG; static gboolean -mu_guile_scm_is_msg (SCM scm) +mu_guile_scm_is_msg(SCM scm) { return SCM_NIMP(scm) && (long)SCM_CAR(scm) == MSG_TAG; } SCM -mu_guile_msg_to_scm (MuMsg *msg) +mu_guile_msg_to_scm(MuMsg* msg) { - MuMsgWrapper *msgwrap; + MuMsgWrapper* msgwrap; - g_return_val_if_fail (msg, SCM_UNDEFINED); + g_return_val_if_fail(msg, SCM_UNDEFINED); - msgwrap = (MuMsgWrapper*)scm_gc_malloc (sizeof (MuMsgWrapper), "msg"); - msgwrap->_msg = msg; + msgwrap = (MuMsgWrapper*)scm_gc_malloc(sizeof(MuMsgWrapper), "msg"); + msgwrap->_msg = msg; msgwrap->_unrefme = FALSE; - SCM_RETURN_NEWSMOB (MSG_TAG, msgwrap); + SCM_RETURN_NEWSMOB(MSG_TAG, msgwrap); } struct _FlagData { MuFlags flags; - SCM lst; + SCM lst; }; typedef struct _FlagData FlagData; - -#define MU_GUILE_INITIALIZED_OR_ERROR \ - do { \ - if (!(mu_guile_initialized())) { \ - mu_guile_error (FUNC_NAME, 0, \ - "mu not initialized; call mu:initialize", \ - SCM_UNDEFINED); \ - return SCM_UNSPECIFIED; \ - } \ +#define MU_GUILE_INITIALIZED_OR_ERROR \ + do { \ + if (!(mu_guile_initialized())) { \ + mu_guile_error(FUNC_NAME, \ + 0, \ + "mu not initialized; call mu:initialize", \ + SCM_UNDEFINED); \ + return SCM_UNSPECIFIED; \ + } \ } while (0) - static void -check_flag (MuFlags flag, FlagData *fdata) +check_flag(MuFlags flag, FlagData* fdata) { SCM flag_scm; @@ -102,225 +99,211 @@ check_flag (MuFlags flag, FlagData *fdata) switch (flag) { case MU_FLAG_NONE: break; - case MU_FLAG_NEW: flag_scm = SYMB_FLAG_NEW; break; - case MU_FLAG_PASSED: flag_scm = SYMB_FLAG_PASSED; break; - case MU_FLAG_REPLIED: flag_scm = SYMB_FLAG_REPLIED; break; - case MU_FLAG_SEEN: flag_scm = SYMB_FLAG_SEEN; break; - case MU_FLAG_TRASHED: flag_scm = SYMB_FLAG_TRASHED; break; - case MU_FLAG_SIGNED: flag_scm = SYMB_FLAG_SIGNED; break; - case MU_FLAG_DRAFT: flag_scm = SYMB_FLAG_DRAFT; break; - case MU_FLAG_FLAGGED: flag_scm = SYMB_FLAG_FLAGGED; break; - case MU_FLAG_ENCRYPTED: flag_scm = SYMB_FLAG_ENCRYPTED; break; + case MU_FLAG_NEW: flag_scm = SYMB_FLAG_NEW; break; + case MU_FLAG_PASSED: flag_scm = SYMB_FLAG_PASSED; break; + case MU_FLAG_REPLIED: flag_scm = SYMB_FLAG_REPLIED; break; + case MU_FLAG_SEEN: flag_scm = SYMB_FLAG_SEEN; break; + case MU_FLAG_TRASHED: flag_scm = SYMB_FLAG_TRASHED; break; + case MU_FLAG_SIGNED: flag_scm = SYMB_FLAG_SIGNED; break; + case MU_FLAG_DRAFT: flag_scm = SYMB_FLAG_DRAFT; break; + case MU_FLAG_FLAGGED: flag_scm = SYMB_FLAG_FLAGGED; break; + case MU_FLAG_ENCRYPTED: flag_scm = SYMB_FLAG_ENCRYPTED; break; case MU_FLAG_HAS_ATTACH: flag_scm = SYMB_FLAG_HAS_ATTACH; break; - case MU_FLAG_UNREAD: flag_scm = SYMB_FLAG_UNREAD; break; - case MU_FLAG_LIST: flag_scm = SYMB_FLAG_LIST; break; + case MU_FLAG_UNREAD: flag_scm = SYMB_FLAG_UNREAD; break; + case MU_FLAG_LIST: flag_scm = SYMB_FLAG_LIST; break; default: flag_scm = SCM_UNDEFINED; } - fdata->lst = scm_append_x - (scm_list_2(fdata->lst, - scm_list_1 (flag_scm))); + fdata->lst = scm_append_x(scm_list_2(fdata->lst, scm_list_1(flag_scm))); } static SCM -get_flags_scm (MuMsg *msg) +get_flags_scm(MuMsg* msg) { FlagData fdata; - fdata.flags = mu_msg_get_flags (msg); + fdata.flags = mu_msg_get_flags(msg); fdata.lst = SCM_EOL; - mu_flags_foreach ((MuFlagsForeachFunc)check_flag, &fdata); + mu_flags_foreach((MuFlagsForeachFunc)check_flag, &fdata); return fdata.lst; } - static SCM -get_prio_scm (MuMsg *msg) +get_prio_scm(MuMsg* msg) { - switch (mu_msg_get_prio (msg)) { + switch (mu_msg_get_prio(msg)) { + case MU_MSG_PRIO_LOW: return SYMB_PRIO_LOW; + case MU_MSG_PRIO_NORMAL: return SYMB_PRIO_NORMAL; + case MU_MSG_PRIO_HIGH: return SYMB_PRIO_HIGH; - case MU_MSG_PRIO_LOW: return SYMB_PRIO_LOW; - case MU_MSG_PRIO_NORMAL: return SYMB_PRIO_NORMAL; - case MU_MSG_PRIO_HIGH: return SYMB_PRIO_HIGH; - - default: - g_return_val_if_reached (SCM_UNDEFINED); + default: g_return_val_if_reached(SCM_UNDEFINED); } } static SCM -msg_string_list_field (MuMsg *msg, MuMsgFieldId mfid) +msg_string_list_field(MuMsg* msg, MuMsgFieldId mfid) { - SCM scmlst; - const GSList *lst; + SCM scmlst; + const GSList* lst; - lst = mu_msg_get_field_string_list (msg, mfid); + lst = mu_msg_get_field_string_list(msg, mfid); - for (scmlst = SCM_EOL; lst; - lst = g_slist_next(lst)) { + for (scmlst = SCM_EOL; lst; lst = g_slist_next(lst)) { SCM item; - item = scm_list_1 - (mu_guile_scm_from_str((const char*)lst->data)); - scmlst = scm_append_x (scm_list_2(scmlst, item)); + item = scm_list_1(mu_guile_scm_from_str((const char*)lst->data)); + scmlst = scm_append_x(scm_list_2(scmlst, item)); } return scmlst; } - static SCM -get_body (MuMsg *msg, gboolean html) +get_body(MuMsg* msg, gboolean html) { - SCM data; - const char* body; + SCM data; + const char* body; MuMsgOptions opts; opts = MU_MSG_OPTION_NONE; if (html) - body = mu_msg_get_body_html (msg, opts); + body = mu_msg_get_body_html(msg, opts); else - body = mu_msg_get_body_text (msg, opts); + body = mu_msg_get_body_text(msg, opts); if (body) - data = mu_guile_scm_from_str (body); + data = mu_guile_scm_from_str(body); else data = SCM_BOOL_F; /* explicitly close the file backend, so we won't run of fds */ - mu_msg_unload_msg_file (msg); + mu_msg_unload_msg_file(msg); return data; } - -SCM_DEFINE (get_field, "mu:c:get-field", 2, 0, 0, - (SCM MSG, SCM FIELD), - "Get the field FIELD from message MSG.\n") +SCM_DEFINE(get_field, + "mu:c:get-field", + 2, + 0, + 0, + (SCM MSG, SCM FIELD), + "Get the field FIELD from message MSG.\n") #define FUNC_NAME s_get_field { - MuMsgWrapper *msgwrap; - MuMsgFieldId mfid; - msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); + MuMsgWrapper* msgwrap; + MuMsgFieldId mfid; + msgwrap = (MuMsgWrapper*)SCM_CDR(MSG); MU_GUILE_INITIALIZED_OR_ERROR; - SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME); + SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME); - mfid = scm_to_int (FIELD); - SCM_ASSERT (mfid < MU_MSG_FIELD_ID_NUM || - mfid == MU_GUILE_MSG_FIELD_ID_TIMESTAMP, - FIELD, SCM_ARG2, FUNC_NAME); + mfid = scm_to_int(FIELD); + SCM_ASSERT(mfid < MU_MSG_FIELD_ID_NUM || mfid == MU_GUILE_MSG_FIELD_ID_TIMESTAMP, + FIELD, + SCM_ARG2, + FUNC_NAME); switch (mfid) { - case MU_MSG_FIELD_ID_PRIO: return get_prio_scm (msgwrap->_msg); - case MU_MSG_FIELD_ID_FLAGS: return get_flags_scm (msgwrap->_msg); + case MU_MSG_FIELD_ID_PRIO: return get_prio_scm(msgwrap->_msg); + case MU_MSG_FIELD_ID_FLAGS: return get_flags_scm(msgwrap->_msg); - case MU_MSG_FIELD_ID_BODY_HTML: - return get_body (msgwrap->_msg, TRUE); - case MU_MSG_FIELD_ID_BODY_TEXT: - return get_body (msgwrap->_msg, FALSE); + case MU_MSG_FIELD_ID_BODY_HTML: return get_body(msgwrap->_msg, TRUE); + case MU_MSG_FIELD_ID_BODY_TEXT: return get_body(msgwrap->_msg, FALSE); /* our pseudo-field; we get it from the message file */ case MU_GUILE_MSG_FIELD_ID_TIMESTAMP: - return scm_from_uint ( - (unsigned)mu_msg_get_timestamp(msgwrap->_msg)); + return scm_from_uint((unsigned)mu_msg_get_timestamp(msgwrap->_msg)); default: break; } - switch (mu_msg_field_type (mfid)) { + switch (mu_msg_field_type(mfid)) { case MU_MSG_FIELD_TYPE_STRING: - return mu_guile_scm_from_str - (mu_msg_get_field_string(msgwrap->_msg, mfid)); + return mu_guile_scm_from_str(mu_msg_get_field_string(msgwrap->_msg, mfid)); case MU_MSG_FIELD_TYPE_BYTESIZE: case MU_MSG_FIELD_TYPE_TIME_T: - return scm_from_uint ( - mu_msg_get_field_numeric (msgwrap->_msg, mfid)); + return scm_from_uint(mu_msg_get_field_numeric(msgwrap->_msg, mfid)); case MU_MSG_FIELD_TYPE_INT: - return scm_from_int ( - mu_msg_get_field_numeric (msgwrap->_msg, mfid)); - case MU_MSG_FIELD_TYPE_STRING_LIST: - return msg_string_list_field (msgwrap->_msg, mfid); - default: - SCM_ASSERT (0, FIELD, SCM_ARG2, FUNC_NAME); + return scm_from_int(mu_msg_get_field_numeric(msgwrap->_msg, mfid)); + case MU_MSG_FIELD_TYPE_STRING_LIST: return msg_string_list_field(msgwrap->_msg, mfid); + default: SCM_ASSERT(0, FIELD, SCM_ARG2, FUNC_NAME); } } #undef FUNC_NAME - - struct _EachContactData { - SCM lst; + SCM lst; MuMsgContactType ctype; }; typedef struct _EachContactData EachContactData; static void -contacts_to_list (MuMsgContact *contact, EachContactData *ecdata) +contacts_to_list(MuMsgContact* contact, EachContactData* ecdata) { SCM item; if (ecdata->ctype != MU_MSG_CONTACT_TYPE_ALL && - mu_msg_contact_type (contact) != ecdata->ctype) + mu_msg_contact_type(contact) != ecdata->ctype) return; - item = scm_list_1 - (scm_cons - (mu_guile_scm_from_str(mu_msg_contact_name (contact)), - mu_guile_scm_from_str(mu_msg_contact_email (contact)))); + item = scm_list_1(scm_cons(mu_guile_scm_from_str(mu_msg_contact_name(contact)), + mu_guile_scm_from_str(mu_msg_contact_email(contact)))); - ecdata->lst = scm_append_x (scm_list_2(ecdata->lst, item)); + ecdata->lst = scm_append_x(scm_list_2(ecdata->lst, item)); } - -SCM_DEFINE (get_contacts, "mu:c:get-contacts", 2, 0, 0, - (SCM MSG, SCM CONTACT_TYPE), - "Get a list of contact information pairs.\n") +SCM_DEFINE(get_contacts, + "mu:c:get-contacts", + 2, + 0, + 0, + (SCM MSG, SCM CONTACT_TYPE), + "Get a list of contact information pairs.\n") #define FUNC_NAME s_get_contacts { - MuMsgWrapper *msgwrap; + MuMsgWrapper* msgwrap; EachContactData ecdata; MU_GUILE_INITIALIZED_OR_ERROR; - SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_symbol_p (CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE), - CONTACT_TYPE, SCM_ARG2, FUNC_NAME); + SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_symbol_p(CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE), + CONTACT_TYPE, + SCM_ARG2, + FUNC_NAME); if (CONTACT_TYPE == SCM_BOOL_F) return SCM_UNSPECIFIED; /* nothing to do */ else if (CONTACT_TYPE == SCM_BOOL_T) ecdata.ctype = MU_MSG_CONTACT_TYPE_ALL; else { - if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_TO)) + if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_TO)) ecdata.ctype = MU_MSG_CONTACT_TYPE_TO; - else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_CC)) + else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_CC)) ecdata.ctype = MU_MSG_CONTACT_TYPE_CC; - else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_BCC)) + else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_BCC)) ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC; - else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_FROM)) + else if (scm_is_eq(CONTACT_TYPE, SYMB_CONTACT_FROM)) ecdata.ctype = MU_MSG_CONTACT_TYPE_FROM; else { - mu_guile_error (FUNC_NAME, 0, "invalid contact type", - SCM_UNDEFINED); + mu_guile_error(FUNC_NAME, 0, "invalid contact type", SCM_UNDEFINED); return SCM_UNSPECIFIED; } } ecdata.lst = SCM_EOL; - msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); - #pragma GCC diagnostic push + msgwrap = (MuMsgWrapper*)SCM_CDR(MSG); +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" - mu_msg_contact_foreach (msgwrap->_msg, - (MuMsgContactForeachFunc)contacts_to_list, - &ecdata); + mu_msg_contact_foreach(msgwrap->_msg, (MuMsgContactForeachFunc)contacts_to_list, &ecdata); #pragma GCC diagnostic pop /* explicitly close the file backend, so we won't run out of fds */ - mu_msg_unload_msg_file (msgwrap->_msg); + mu_msg_unload_msg_file(msgwrap->_msg); return ecdata.lst; } @@ -333,144 +316,149 @@ struct _AttInfo { typedef struct _AttInfo AttInfo; static void -each_part (MuMsg *msg, MuMsgPart *part, AttInfo *attinfo) +each_part(MuMsg* msg, MuMsgPart* part, AttInfo* attinfo) { char *mime_type, *filename; - SCM elm; + SCM elm; if (!part->type) return; - if (attinfo->attachments_only && - !mu_msg_part_maybe_attachment (part)) + if (attinfo->attachments_only && !mu_msg_part_maybe_attachment(part)) return; - mime_type = g_strdup_printf ("%s/%s", part->type, part->subtype); - filename = mu_msg_part_get_filename (part, FALSE); + mime_type = g_strdup_printf("%s/%s", part->type, part->subtype); + filename = mu_msg_part_get_filename(part, FALSE); - elm = scm_list_5 ( - /* msg */ - mu_guile_scm_from_str (mu_msg_get_path(msg)), - /* index */ - scm_from_uint(part->index), - /* filename or #f */ - filename ? mu_guile_scm_from_str (filename) : SCM_BOOL_F, - /* mime-type */ - mime_type ? mu_guile_scm_from_str (mime_type): SCM_BOOL_F, - /* size */ - part->size > 0 ? scm_from_uint (part->size) : SCM_BOOL_F); + elm = scm_list_5( + /* msg */ + mu_guile_scm_from_str(mu_msg_get_path(msg)), + /* index */ + scm_from_uint(part->index), + /* filename or #f */ + filename ? mu_guile_scm_from_str(filename) : SCM_BOOL_F, + /* mime-type */ + mime_type ? mu_guile_scm_from_str(mime_type) : SCM_BOOL_F, + /* size */ + part->size > 0 ? scm_from_uint(part->size) : SCM_BOOL_F); - g_free (mime_type); - g_free (filename); + g_free(mime_type); + g_free(filename); - attinfo->attlist = scm_cons (elm, attinfo->attlist); + attinfo->attlist = scm_cons(elm, attinfo->attlist); } - -SCM_DEFINE (get_parts, "mu:c:get-parts", 1, 1, 0, - (SCM MSG, SCM ATTS_ONLY), - "Get the list of mime-parts for MSG. If ATTS_ONLY is #t, only" - "get parts that are (look like) attachments. The resulting list has " - "elements which are list of the form (index name mime-type size).\n") +SCM_DEFINE(get_parts, + "mu:c:get-parts", + 1, + 1, + 0, + (SCM MSG, SCM ATTS_ONLY), + "Get the list of mime-parts for MSG. If ATTS_ONLY is #t, only" + "get parts that are (look like) attachments. The resulting list has " + "elements which are list of the form (index name mime-type size).\n") #define FUNC_NAME s_get_parts { - MuMsgWrapper *msgwrap; - AttInfo attinfo; + MuMsgWrapper* msgwrap; + AttInfo attinfo; MU_GUILE_INITIALIZED_OR_ERROR; - SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME); + SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME); - attinfo.attlist = SCM_EOL; /* empty list */ + attinfo.attlist = SCM_EOL; /* empty list */ attinfo.attachments_only = ATTS_ONLY == SCM_BOOL_T ? TRUE : FALSE; - msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); - mu_msg_part_foreach (msgwrap->_msg, MU_MSG_OPTION_NONE, - (MuMsgPartForeachFunc)each_part, - &attinfo); + msgwrap = (MuMsgWrapper*)SCM_CDR(MSG); + mu_msg_part_foreach(msgwrap->_msg, + MU_MSG_OPTION_NONE, + (MuMsgPartForeachFunc)each_part, + &attinfo); /* explicitly close the file backend, so we won't run of fds */ - mu_msg_unload_msg_file (msgwrap->_msg); + mu_msg_unload_msg_file(msgwrap->_msg); return attinfo.attlist; } #undef FUNC_NAME - -SCM_DEFINE (get_header, "mu:c:get-header", 2, 0, 0, - (SCM MSG, SCM HEADER), "Get an arbitrary HEADER from MSG.\n") +SCM_DEFINE(get_header, + "mu:c:get-header", + 2, + 0, + 0, + (SCM MSG, SCM HEADER), + "Get an arbitrary HEADER from MSG.\n") #define FUNC_NAME s_get_header { - MuMsgWrapper *msgwrap; - char *header; - SCM val; + MuMsgWrapper* msgwrap; + char* header; + SCM val; MU_GUILE_INITIALIZED_OR_ERROR; - SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_is_string (HEADER)||HEADER==SCM_UNDEFINED, - HEADER, SCM_ARG2, FUNC_NAME); + SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_is_string(HEADER) || HEADER == SCM_UNDEFINED, HEADER, SCM_ARG2, FUNC_NAME); - msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); - header = scm_to_utf8_string (HEADER); - val = mu_guile_scm_from_str - (mu_msg_get_header(msgwrap->_msg, header)); - free (header); + msgwrap = (MuMsgWrapper*)SCM_CDR(MSG); + header = scm_to_utf8_string(HEADER); + val = mu_guile_scm_from_str(mu_msg_get_header(msgwrap->_msg, header)); + free(header); /* explicitly close the file backend, so we won't run of fds */ - mu_msg_unload_msg_file (msgwrap->_msg); + mu_msg_unload_msg_file(msgwrap->_msg); return val; } #undef FUNC_NAME static Mu::Option -get_query_results (Mu::Store& store, const char* expr, int maxnum) +get_query_results(Mu::Store& store, const char* expr, int maxnum) { Mu::Query query(store); - return query.run(expr, MU_MSG_FIELD_ID_NONE, - Mu::QueryFlags::None, maxnum); + return query.run(expr, MU_MSG_FIELD_ID_NONE, Mu::QueryFlags::None, maxnum); } - -SCM_DEFINE (for_each_message, "mu:c:for-each-message", 3, 0, 0, - (SCM FUNC, SCM EXPR, SCM MAXNUM), -"Call FUNC for each msg in the message store matching EXPR. EXPR is" -"either a string containing a mu search expression or a boolean; in the former " -"case, limit the messages to only those matching the expression, in the " -"latter case, match /all/ messages if the EXPR equals #t, and match " -"none if EXPR equals #f.") +SCM_DEFINE(for_each_message, + "mu:c:for-each-message", + 3, + 0, + 0, + (SCM FUNC, SCM EXPR, SCM MAXNUM), + "Call FUNC for each msg in the message store matching EXPR. EXPR is" + "either a string containing a mu search expression or a boolean; in the former " + "case, limit the messages to only those matching the expression, in the " + "latter case, match /all/ messages if the EXPR equals #t, and match " + "none if EXPR equals #f.") #define FUNC_NAME s_for_each_message { char* expr{}; MU_GUILE_INITIALIZED_OR_ERROR; - SCM_ASSERT (scm_procedure_p (FUNC), FUNC, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_is_bool(EXPR) || scm_is_string (EXPR), - EXPR, SCM_ARG2, FUNC_NAME); - SCM_ASSERT (scm_is_integer (MAXNUM), MAXNUM, SCM_ARG3, FUNC_NAME); + SCM_ASSERT(scm_procedure_p(FUNC), FUNC, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_is_bool(EXPR) || scm_is_string(EXPR), EXPR, SCM_ARG2, FUNC_NAME); + SCM_ASSERT(scm_is_integer(MAXNUM), MAXNUM, SCM_ARG3, FUNC_NAME); if (EXPR == SCM_BOOL_F) return SCM_UNSPECIFIED; /* nothing to do */ if (EXPR == SCM_BOOL_T) - expr = strdup (""); /* note, "" matches *all* messages */ + expr = strdup(""); /* note, "" matches *all* messages */ else expr = scm_to_utf8_string(EXPR); - const auto res{get_query_results(mu_guile_store(), expr, - scm_to_int(MAXNUM))}; - free (expr); + const auto res{get_query_results(mu_guile_store(), expr, scm_to_int(MAXNUM))}; + free(expr); if (!res) return SCM_UNSPECIFIED; - for (auto&& mi: *res) { + for (auto&& mi : *res) { auto msg{mi.floating_msg()}; if (msg) { - auto msgsmob{mu_guile_msg_to_scm (mu_msg_ref(msg))}; - scm_call_1 (FUNC, msgsmob); + auto msgsmob{mu_guile_msg_to_scm(mu_msg_ref(msg))}; + scm_call_1(FUNC, msgsmob); } } @@ -478,90 +466,85 @@ SCM_DEFINE (for_each_message, "mu:c:for-each-message", 3, 0, 0, } #undef FUNC_NAME - static SCM -register_symbol (const char *name) +register_symbol(const char* name) { SCM scm; - scm = scm_from_utf8_symbol (name); - scm_c_define (name, scm); - scm_c_export (name, NULL); + scm = scm_from_utf8_symbol(name); + scm_c_define(name, scm); + scm_c_export(name, NULL); return scm; } static void -define_symbols (void) +define_symbols(void) { - SYMB_CONTACT_TO = register_symbol ("mu:contact:to"); - SYMB_CONTACT_CC = register_symbol ("mu:contact:cc"); - SYMB_CONTACT_FROM = register_symbol ("mu:contact:from"); - SYMB_CONTACT_BCC = register_symbol ("mu:contact:bcc"); + SYMB_CONTACT_TO = register_symbol("mu:contact:to"); + SYMB_CONTACT_CC = register_symbol("mu:contact:cc"); + SYMB_CONTACT_FROM = register_symbol("mu:contact:from"); + SYMB_CONTACT_BCC = register_symbol("mu:contact:bcc"); - SYMB_PRIO_LOW = register_symbol ("mu:prio:low"); - SYMB_PRIO_NORMAL = register_symbol ("mu:prio:normal"); - SYMB_PRIO_HIGH = register_symbol ("mu:prio:high"); + SYMB_PRIO_LOW = register_symbol("mu:prio:low"); + SYMB_PRIO_NORMAL = register_symbol("mu:prio:normal"); + SYMB_PRIO_HIGH = register_symbol("mu:prio:high"); - SYMB_FLAG_NEW = register_symbol ("mu:flag:new"); - SYMB_FLAG_PASSED = register_symbol ("mu:flag:passed"); - SYMB_FLAG_REPLIED = register_symbol ("mu:flag:replied"); - SYMB_FLAG_SEEN = register_symbol ("mu:flag:seen"); - SYMB_FLAG_TRASHED = register_symbol ("mu:flag:trashed"); - SYMB_FLAG_DRAFT = register_symbol ("mu:flag:draft"); - SYMB_FLAG_FLAGGED = register_symbol ("mu:flag:flagged"); - SYMB_FLAG_SIGNED = register_symbol ("mu:flag:signed"); - SYMB_FLAG_ENCRYPTED = register_symbol ("mu:flag:encrypted"); - SYMB_FLAG_HAS_ATTACH = register_symbol ("mu:flag:has-attach"); - SYMB_FLAG_UNREAD = register_symbol ("mu:flag:unread"); + SYMB_FLAG_NEW = register_symbol("mu:flag:new"); + SYMB_FLAG_PASSED = register_symbol("mu:flag:passed"); + SYMB_FLAG_REPLIED = register_symbol("mu:flag:replied"); + SYMB_FLAG_SEEN = register_symbol("mu:flag:seen"); + SYMB_FLAG_TRASHED = register_symbol("mu:flag:trashed"); + SYMB_FLAG_DRAFT = register_symbol("mu:flag:draft"); + SYMB_FLAG_FLAGGED = register_symbol("mu:flag:flagged"); + SYMB_FLAG_SIGNED = register_symbol("mu:flag:signed"); + SYMB_FLAG_ENCRYPTED = register_symbol("mu:flag:encrypted"); + SYMB_FLAG_HAS_ATTACH = register_symbol("mu:flag:has-attach"); + SYMB_FLAG_UNREAD = register_symbol("mu:flag:unread"); - SYMB_FLAG_LIST = register_symbol ("mu:flag:list"); + SYMB_FLAG_LIST = register_symbol("mu:flag:list"); } - -static struct { +static struct { const char* name; - unsigned val; + unsigned val; } VAR_PAIRS[] = { - { "mu:field:bcc", MU_MSG_FIELD_ID_BCC }, - { "mu:field:body-html", MU_MSG_FIELD_ID_BODY_HTML }, - { "mu:field:body-txt", MU_MSG_FIELD_ID_BODY_TEXT }, - { "mu:field:cc", MU_MSG_FIELD_ID_CC }, - { "mu:field:date", MU_MSG_FIELD_ID_DATE }, - { "mu:field:flags", MU_MSG_FIELD_ID_FLAGS }, - { "mu:field:from", MU_MSG_FIELD_ID_FROM }, - { "mu:field:maildir", MU_MSG_FIELD_ID_MAILDIR }, - { "mu:field:message-id",MU_MSG_FIELD_ID_MSGID }, - { "mu:field:path", MU_MSG_FIELD_ID_PATH }, - { "mu:field:prio", MU_MSG_FIELD_ID_PRIO }, - { "mu:field:refs", MU_MSG_FIELD_ID_REFS }, - { "mu:field:size", MU_MSG_FIELD_ID_SIZE }, - { "mu:field:subject", MU_MSG_FIELD_ID_SUBJECT }, - { "mu:field:tags", MU_MSG_FIELD_ID_TAGS }, - { "mu:field:to", MU_MSG_FIELD_ID_TO }, + {"mu:field:bcc", MU_MSG_FIELD_ID_BCC}, + {"mu:field:body-html", MU_MSG_FIELD_ID_BODY_HTML}, + {"mu:field:body-txt", MU_MSG_FIELD_ID_BODY_TEXT}, + {"mu:field:cc", MU_MSG_FIELD_ID_CC}, + {"mu:field:date", MU_MSG_FIELD_ID_DATE}, + {"mu:field:flags", MU_MSG_FIELD_ID_FLAGS}, + {"mu:field:from", MU_MSG_FIELD_ID_FROM}, + {"mu:field:maildir", MU_MSG_FIELD_ID_MAILDIR}, + {"mu:field:message-id", MU_MSG_FIELD_ID_MSGID}, + {"mu:field:path", MU_MSG_FIELD_ID_PATH}, + {"mu:field:prio", MU_MSG_FIELD_ID_PRIO}, + {"mu:field:refs", MU_MSG_FIELD_ID_REFS}, + {"mu:field:size", MU_MSG_FIELD_ID_SIZE}, + {"mu:field:subject", MU_MSG_FIELD_ID_SUBJECT}, + {"mu:field:tags", MU_MSG_FIELD_ID_TAGS}, + {"mu:field:to", MU_MSG_FIELD_ID_TO}, - /* non-Xapian field: timestamp */ - { "mu:field:timestamp", MU_GUILE_MSG_FIELD_ID_TIMESTAMP } -}; + /* non-Xapian field: timestamp */ + {"mu:field:timestamp", MU_GUILE_MSG_FIELD_ID_TIMESTAMP}}; static void -define_vars (void) +define_vars(void) { unsigned u; for (u = 0; u != G_N_ELEMENTS(VAR_PAIRS); ++u) { - scm_c_define (VAR_PAIRS[u].name, - scm_from_uint (VAR_PAIRS[u].val)); - scm_c_export (VAR_PAIRS[u].name, NULL); + scm_c_define(VAR_PAIRS[u].name, scm_from_uint(VAR_PAIRS[u].val)); + scm_c_export(VAR_PAIRS[u].name, NULL); } } - static SCM -msg_mark (SCM msg_smob) +msg_mark(SCM msg_smob) { - MuMsgWrapper *msgwrap; - msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + MuMsgWrapper* msgwrap; + msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob); msgwrap->_unrefme = TRUE; @@ -569,48 +552,46 @@ msg_mark (SCM msg_smob) } static size_t -msg_free (SCM msg_smob) +msg_free(SCM msg_smob) { - MuMsgWrapper *msgwrap; - msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + MuMsgWrapper* msgwrap; + msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob); if (msgwrap->_unrefme) - mu_msg_unref (msgwrap->_msg); + mu_msg_unref(msgwrap->_msg); - return sizeof (MuMsgWrapper); + return sizeof(MuMsgWrapper); } static int -msg_print (SCM msg_smob, SCM port, scm_print_state * pstate) +msg_print(SCM msg_smob, SCM port, scm_print_state* pstate) { - MuMsgWrapper *msgwrap; - msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + MuMsgWrapper* msgwrap; + msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob); - scm_puts ("#_msg), - port); + scm_puts(mu_msg_get_path(msgwrap->_msg), port); - scm_puts (">", port); + scm_puts(">", port); return 1; } - void* -mu_guile_message_init (void *data) +mu_guile_message_init(void* data) { - MSG_TAG = scm_make_smob_type ("msg", sizeof(MuMsgWrapper)); + MSG_TAG = scm_make_smob_type("msg", sizeof(MuMsgWrapper)); - scm_set_smob_mark (MSG_TAG, msg_mark); - scm_set_smob_free (MSG_TAG, msg_free); - scm_set_smob_print (MSG_TAG, msg_print); + scm_set_smob_mark(MSG_TAG, msg_mark); + scm_set_smob_free(MSG_TAG, msg_free); + scm_set_smob_print(MSG_TAG, msg_print); - define_vars (); - define_symbols (); + define_vars(); + define_symbols(); #ifndef SCM_MAGIC_SNARFER #include "mu-guile-message.x" diff --git a/guile/mu-guile-message.hh b/guile/mu-guile-message.hh index 04a5c789..9ac84ce3 100644 --- a/guile/mu-guile-message.hh +++ b/guile/mu-guile-message.hh @@ -27,6 +27,8 @@ * * @return */ -extern "C" { void* mu_guile_message_init (void *data);} +extern "C" { +void* mu_guile_message_init(void* data); +} #endif /*MU_GUILE_MESSAGE_HH__*/ diff --git a/guile/mu-guile.cc b/guile/mu-guile.cc index bb30a0f1..5d0a6850 100644 --- a/guile/mu-guile.cc +++ b/guile/mu-guile.cc @@ -36,58 +36,58 @@ using namespace Mu; SCM -mu_guile_scm_from_str (const char *str) +mu_guile_scm_from_str(const char* str) { if (!str) return SCM_BOOL_F; else - return scm_from_stringn (str, strlen(str), "UTF-8", - SCM_FAILED_CONVERSION_QUESTION_MARK); + return scm_from_stringn(str, + strlen(str), + "UTF-8", + SCM_FAILED_CONVERSION_QUESTION_MARK); } SCM -mu_guile_error (const char *func_name, int status, - const char *fmt, SCM args) +mu_guile_error(const char* func_name, int status, const char* fmt, SCM args) { - scm_error_scm (scm_from_locale_symbol ("MuError"), - scm_from_utf8_string (func_name ? func_name : ""), - scm_from_utf8_string (fmt), args, - scm_list_1 (scm_from_int (status))); + scm_error_scm(scm_from_locale_symbol("MuError"), + scm_from_utf8_string(func_name ? func_name : ""), + scm_from_utf8_string(fmt), + args, + scm_list_1(scm_from_int(status))); return SCM_UNSPECIFIED; } SCM -mu_guile_g_error (const char *func_name, GError *err) +mu_guile_g_error(const char* func_name, GError* err) { - scm_error_scm (scm_from_locale_symbol ("MuError"), - scm_from_utf8_string (func_name), - scm_from_utf8_string (err ? err->message : "error"), - SCM_UNDEFINED, SCM_UNDEFINED); + scm_error_scm(scm_from_locale_symbol("MuError"), + scm_from_utf8_string(func_name), + scm_from_utf8_string(err ? err->message : "error"), + SCM_UNDEFINED, + SCM_UNDEFINED); return SCM_UNSPECIFIED; } - - /* there can be only one */ static std::unique_ptr StoreSingleton; static gboolean -mu_guile_init_instance (const char *muhome) try -{ - setlocale (LC_ALL, ""); - if (!mu_runtime_init (muhome, "guile", true) || StoreSingleton) +mu_guile_init_instance(const char* muhome) +try { + setlocale(LC_ALL, ""); + if (!mu_runtime_init(muhome, "guile", true) || StoreSingleton) return FALSE; - StoreSingleton = std::make_unique( - mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)); + StoreSingleton = std::make_unique(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)); - g_debug ("mu-guile: opened store @ %s (n=%zu); maildir: %s", - StoreSingleton->metadata().database_path.c_str(), - StoreSingleton->size(), - StoreSingleton->metadata().root_maildir.c_str()); + g_debug("mu-guile: opened store @ %s (n=%zu); maildir: %s", + StoreSingleton->metadata().database_path.c_str(), + StoreSingleton->size(), + StoreSingleton->metadata().root_maildir.c_str()); return TRUE; @@ -96,16 +96,15 @@ mu_guile_init_instance (const char *muhome) try } static void -mu_guile_uninit_instance () +mu_guile_uninit_instance() { StoreSingleton.reset(); - mu_runtime_uninit (); + mu_runtime_uninit(); } - Mu::Store& -mu_guile_store () +mu_guile_store() { if (!StoreSingleton) g_error("mu guile not initialized"); @@ -114,124 +113,130 @@ mu_guile_store () } gboolean -mu_guile_initialized () +mu_guile_initialized() { - g_debug ("initialized ? %u", !!StoreSingleton); + g_debug("initialized ? %u", !!StoreSingleton); return !!StoreSingleton; } - -SCM_DEFINE_PUBLIC (mu_initialize, "mu:initialize", 0, 1, 0, - (SCM MUHOME), - "Initialize mu - needed before you call any of the other " - "functions. Optionally, you can provide MUHOME which should be an " - "absolute path to your mu home directory " - "-- typically, the default, ~/.cache/mu, should be just fine.") +SCM_DEFINE_PUBLIC(mu_initialize, + "mu:initialize", + 0, + 1, + 0, + (SCM MUHOME), + "Initialize mu - needed before you call any of the other " + "functions. Optionally, you can provide MUHOME which should be an " + "absolute path to your mu home directory " + "-- typically, the default, ~/.cache/mu, should be just fine.") #define FUNC_NAME s_mu_initialize { - char *muhome; + char* muhome; gboolean rv; - SCM_ASSERT (scm_is_string (MUHOME) || MUHOME == SCM_BOOL_F || - SCM_UNBNDP(MUHOME), MUHOME, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_is_string(MUHOME) || MUHOME == SCM_BOOL_F || SCM_UNBNDP(MUHOME), + MUHOME, + SCM_ARG1, + FUNC_NAME); if (mu_guile_initialized()) - return mu_guile_error (FUNC_NAME, 0, "Already initialized", - SCM_UNSPECIFIED); + return mu_guile_error(FUNC_NAME, 0, "Already initialized", SCM_UNSPECIFIED); if (SCM_UNBNDP(MUHOME) || MUHOME == SCM_BOOL_F) muhome = NULL; else - muhome = scm_to_utf8_string (MUHOME); + muhome = scm_to_utf8_string(MUHOME); - rv = mu_guile_init_instance (muhome); - free (muhome); + rv = mu_guile_init_instance(muhome); + free(muhome); if (!rv) - return mu_guile_error (FUNC_NAME, 0, "Failed to initialize mu", - SCM_UNSPECIFIED); + return mu_guile_error(FUNC_NAME, 0, "Failed to initialize mu", SCM_UNSPECIFIED); - g_debug ("mu-guile: initialized @ %s (%p)", - muhome ? muhome : "", StoreSingleton.get()); + g_debug("mu-guile: initialized @ %s (%p)", + muhome ? muhome : "", + StoreSingleton.get()); /* cleanup when we're exiting */ - atexit (mu_guile_uninit_instance); + atexit(mu_guile_uninit_instance); return SCM_UNSPECIFIED; } #undef FUNC_NAME -SCM_DEFINE_PUBLIC (mu_initialized_p, "mu:initialized?", 0, 0, 0, - (void), "Whether mu is initialized or not.\n") +SCM_DEFINE_PUBLIC(mu_initialized_p, + "mu:initialized?", + 0, + 0, + 0, + (void), + "Whether mu is initialized or not.\n") #define FUNC_NAME s_mu_initialized_p { return mu_guile_initialized() ? SCM_BOOL_T : SCM_BOOL_F; } #undef FUNC_NAME - -SCM_DEFINE (log_func, "mu:c:log", 1, 0, 1, (SCM LEVEL, SCM FRM, SCM ARGS), - "log some message at LEVEL using a list of ARGS applied to FRM" - "(in 'simple-format' notation).\n") +SCM_DEFINE(log_func, + "mu:c:log", + 1, + 0, + 1, + (SCM LEVEL, SCM FRM, SCM ARGS), + "log some message at LEVEL using a list of ARGS applied to FRM" + "(in 'simple-format' notation).\n") #define FUNC_NAME s_log_func { - gchar *output; - SCM str; - int level; + gchar* output; + SCM str; + int level; - SCM_ASSERT (scm_integer_p(LEVEL), LEVEL, SCM_ARG1, FUNC_NAME); - SCM_ASSERT (scm_is_string(FRM), FRM, SCM_ARG2, ""); + SCM_ASSERT(scm_integer_p(LEVEL), LEVEL, SCM_ARG1, FUNC_NAME); + SCM_ASSERT(scm_is_string(FRM), FRM, SCM_ARG2, ""); SCM_VALIDATE_REST_ARGUMENT(ARGS); - level = scm_to_int (LEVEL); - if (level != G_LOG_LEVEL_MESSAGE && - level != G_LOG_LEVEL_WARNING && + level = scm_to_int(LEVEL); + if (level != G_LOG_LEVEL_MESSAGE && level != G_LOG_LEVEL_WARNING && level != G_LOG_LEVEL_CRITICAL) - return mu_guile_error (FUNC_NAME, 0, "invalid log level", - SCM_UNSPECIFIED); + return mu_guile_error(FUNC_NAME, 0, "invalid log level", SCM_UNSPECIFIED); - str = scm_simple_format (SCM_BOOL_F, FRM, ARGS); + str = scm_simple_format(SCM_BOOL_F, FRM, ARGS); - if (!scm_is_string (str)) + if (!scm_is_string(str)) return SCM_UNSPECIFIED; - output = scm_to_utf8_string (str); - g_log (G_LOG_DOMAIN, (GLogLevelFlags)level, "%s", output); - free (output); + output = scm_to_utf8_string(str); + g_log(G_LOG_DOMAIN, (GLogLevelFlags)level, "%s", output); + free(output); return SCM_UNSPECIFIED; } #undef FUNC_NAME - -static struct { +static struct { const char* name; - unsigned val; + unsigned val; } VAR_PAIRS[] = { - { "mu:message", G_LOG_LEVEL_MESSAGE }, - { "mu:warning", G_LOG_LEVEL_WARNING }, - { "mu:critical", G_LOG_LEVEL_CRITICAL } -}; + {"mu:message", G_LOG_LEVEL_MESSAGE}, + {"mu:warning", G_LOG_LEVEL_WARNING}, + {"mu:critical", G_LOG_LEVEL_CRITICAL}}; static void -define_vars (void) +define_vars(void) { unsigned u; for (u = 0; u != G_N_ELEMENTS(VAR_PAIRS); ++u) { - scm_c_define (VAR_PAIRS[u].name, - scm_from_uint (VAR_PAIRS[u].val)); - scm_c_export (VAR_PAIRS[u].name, NULL); + scm_c_define(VAR_PAIRS[u].name, scm_from_uint(VAR_PAIRS[u].val)); + scm_c_export(VAR_PAIRS[u].name, NULL); } } - void* -mu_guile_init (void *data) +mu_guile_init(void* data) { - define_vars (); - + define_vars(); #ifndef SCM_MAGIC_SNARFER #include "mu-guile.x" diff --git a/guile/mu-guile.hh b/guile/mu-guile.hh index 6afd71cf..e49699a3 100644 --- a/guile/mu-guile.hh +++ b/guile/mu-guile.hh @@ -24,20 +24,17 @@ #include #include - /** * get the singleton Store instance */ -Mu::Store& mu_guile_store (); - +Mu::Store& mu_guile_store(); /** * whether mu-guile is initialized * * @return TRUE if MuGuile is Initialized, FALSE otherwise */ -gboolean mu_guile_initialized (); - +gboolean mu_guile_initialized(); /** * raise a guile error (based on a GError) @@ -47,8 +44,7 @@ gboolean mu_guile_initialized (); * * @return SCM_UNSPECIFIED */ -SCM mu_guile_g_error (const char *func_name, GError *err); - +SCM mu_guile_g_error(const char* func_name, GError* err); /** * raise a guile error @@ -60,9 +56,7 @@ SCM mu_guile_g_error (const char *func_name, GError *err); * * @return SCM_UNSPECIFIED */ -SCM mu_guile_error (const char *func_name, int status, - const char *fmt, SCM args); - +SCM mu_guile_error(const char* func_name, int status, const char* fmt, SCM args); /** * convert a const char* into an SCM -- either a string or, if str == @@ -73,7 +67,7 @@ SCM mu_guile_error (const char *func_name, int status, * * @return a guile string or #f */ -SCM mu_guile_scm_from_str (const char *str); +SCM mu_guile_scm_from_str(const char* str); /** * Initialize this mu guile module. @@ -82,5 +76,7 @@ SCM mu_guile_scm_from_str (const char *str); * * @return */ -extern "C" { void* mu_guile_init (void *data); } +extern "C" { +void* mu_guile_init(void* data); +} #endif /*__MU_GUILE_H__*/ diff --git a/guile/tests/test-mu-guile.cc b/guile/tests/test-mu-guile.cc index 52e31250..dbf622e4 100644 --- a/guile/tests/test-mu-guile.cc +++ b/guile/tests/test-mu-guile.cc @@ -32,105 +32,103 @@ #include "test-mu-common.hh" #include - /* Tests For The command line interface, uses testdir2 */ static gchar* -fill_database (void) +fill_database(void) { - gchar *cmdline, *tmpdir; - GError *err; + gchar * cmdline, *tmpdir; + GError* err; - tmpdir = test_mu_common_get_random_tmpdir(); - cmdline = g_strdup_printf ( - "/bin/sh -c '" - "%s init --muhome=%s --maildir=%s --quiet; " - "%s index --muhome=%s --quiet'", - MU_PROGRAM, tmpdir, MU_TESTMAILDIR2, - MU_PROGRAM, tmpdir); + tmpdir = test_mu_common_get_random_tmpdir(); + cmdline = g_strdup_printf("/bin/sh -c '" + "%s init --muhome=%s --maildir=%s --quiet; " + "%s index --muhome=%s --quiet'", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + MU_PROGRAM, + tmpdir); if (g_test_verbose()) - g_print ("%s\n", cmdline); + g_print("%s\n", cmdline); - err = NULL; - if (!g_spawn_command_line_sync (cmdline, NULL, NULL, - NULL, &err)) { - g_printerr ("Error: %s\n", err ? err->message : "?"); - g_assert (0); + err = NULL; + if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &err)) { + g_printerr("Error: %s\n", err ? err->message : "?"); + g_assert(0); } - g_free (cmdline); + g_free(cmdline); return tmpdir; } - static void -test_something (const char *what) +test_something(const char* what) { char *dir, *cmdline; - gint result; + gint result; - dir = fill_database (); - cmdline = g_strdup_printf ( - "GUILE_AUTO_COMPILE=0 " - "LD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH " - "%s -q -L %s -e main %s/test-mu-guile.scm " - "--muhome=%s --test=%s", - MU_GUILE_LIBRARY_PATH, - GUILE_BINARY, - MU_GUILE_MODULE_PATH, - ABS_SRCDIR, - dir, - what); + dir = fill_database(); + cmdline = g_strdup_printf("GUILE_AUTO_COMPILE=0 " + "LD_LIBRARY_PATH=%s:$LD_LIBRARY_PATH " + "%s -q -L %s -e main %s/test-mu-guile.scm " + "--muhome=%s --test=%s", + MU_GUILE_LIBRARY_PATH, + GUILE_BINARY, + MU_GUILE_MODULE_PATH, + ABS_SRCDIR, + dir, + what); - if (g_test_verbose ()) - g_print ("cmdline: %s\n", cmdline); + if (g_test_verbose()) + g_print("cmdline: %s\n", cmdline); - result = system (cmdline); - g_assert (result == 0); + result = system(cmdline); + g_assert(result == 0); - g_free (dir); - g_free (cmdline); + g_free(dir); + g_free(cmdline); } static void -test_mu_guile_queries (void) +test_mu_guile_queries(void) { - test_something ("queries"); + test_something("queries"); } static void -test_mu_guile_messages (void) +test_mu_guile_messages(void) { - test_something ("message"); + test_something("message"); } static void -test_mu_guile_stats (void) +test_mu_guile_stats(void) { - test_something ("stats"); + test_something("stats"); } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); if (!set_en_us_utf8_locale()) return 0; /* don't error out... */ - g_test_add_func ("/guile/queries", test_mu_guile_queries); - g_test_add_func ("/guile/message", test_mu_guile_messages); - g_test_add_func ("/guile/stats", test_mu_guile_stats); + g_test_add_func("/guile/queries", test_mu_guile_queries); + g_test_add_func("/guile/message", test_mu_guile_messages); + g_test_add_func("/guile/stats", test_mu_guile_stats); - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| - G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler(NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - rv = g_test_run (); + rv = g_test_run(); return rv; } diff --git a/lib/index/mu-indexer.cc b/lib/index/mu-indexer.cc index 1fd4e1cd..3b578e63 100644 --- a/lib/index/mu-indexer.cc +++ b/lib/index/mu-indexer.cc @@ -41,333 +41,341 @@ using namespace std::chrono_literals; using namespace Mu; struct IndexState { - enum State { Idle, Scanning, Cleaning }; - static const char* name(State s) { - switch(s) { - case Idle: return "idle"; - case Scanning: return "scanning"; - case Cleaning: return "cleaning"; - default: return ""; - } - } + enum State { Idle, Scanning, Cleaning }; + static const char* name(State s) + { + switch (s) { + case Idle: return "idle"; + case Scanning: return "scanning"; + case Cleaning: return "cleaning"; + default: return ""; + } + } - bool operator==(State rhs) const { return state_ == rhs; } + bool operator==(State rhs) const { return state_ == rhs; } - void change_to(State new_state) { - g_debug ("changing indexer state %s->%s", - name((State)state_), name((State)new_state)); - state_ = new_state; - } + void change_to(State new_state) + { + g_debug("changing indexer state %s->%s", + name((State)state_), + name((State)new_state)); + state_ = new_state; + } -private: - State state_{Idle}; + private: + State state_{Idle}; }; struct Indexer::Private { - Private (Mu::Store& store): - store_{store}, - scanner_{store_.metadata().root_maildir, - [this](auto&& path, auto&& statbuf, auto&& info){ - return handler(path, statbuf, info); - }}, - max_message_size_{store_.metadata().max_message_size} { + Private(Mu::Store& store) + : store_{store}, scanner_{store_.metadata().root_maildir, + [this](auto&& path, auto&& statbuf, auto&& info) { + return handler(path, statbuf, info); + }}, + max_message_size_{store_.metadata().max_message_size}, + batch_size_{store_.metadata().batch_size} + { + g_message("created indexer for %s -> %s (batch-size: %zu)", + store.metadata().root_maildir.c_str(), + store.metadata().database_path.c_str(), + batch_size_); + } - g_message ("created indexer for %s -> %s", - store.metadata().root_maildir.c_str(), - store.metadata().database_path.c_str()); - } + ~Private() { stop(); } - ~Private() { stop(); } + bool dir_predicate(const std::string& path, const struct dirent* dirent) const; + bool handler(const std::string& fullpath, struct stat* statbuf, Scanner::HandleType htype); - bool dir_predicate (const std::string& path, const struct dirent* dirent) const; - bool handler (const std::string& fullpath, struct stat *statbuf, - Scanner::HandleType htype); + void maybe_start_worker(); + void worker(); - void maybe_start_worker(); - void worker(); + bool cleanup(); - bool cleanup(); + bool start(const Indexer::Config& conf); + bool stop(); - bool start(const Indexer::Config& conf); - bool stop(); + Indexer::Config conf_; + Store& store_; + Scanner scanner_; + const size_t max_message_size_; - Indexer::Config conf_; - Store& store_; - Scanner scanner_; - const size_t max_message_size_; + time_t dirstamp_{}; + std::size_t max_workers_; + std::vector workers_; + std::thread scanner_worker_; - time_t dirstamp_{}; - std::size_t max_workers_; - std::vector workers_; - std::thread scanner_worker_; + AsyncQueue fq_; - AsyncQueue fq_; + Progress progress_; + IndexState state_; + const size_t batch_size_; /**< Max number of messages added before + * committing */ - Progress progress_; - IndexState state_; - - std::mutex lock_, wlock_; + std::mutex lock_, wlock_; }; - bool -Indexer::Private::handler (const std::string& fullpath, struct stat *statbuf, - Scanner::HandleType htype) +Indexer::Private::handler(const std::string& fullpath, + struct stat* statbuf, + Scanner::HandleType htype) { - switch (htype) { - case Scanner::HandleType::EnterDir: - case Scanner::HandleType::EnterNewCur: { - // in lazy-mode, we ignore this dir if its dirstamp suggest it - // is up-to-date (this is _not_ always true; hence we call it - // lazy-mode); only for actual message dirs, since the dir - // tstamps may not bubble up. - dirstamp_ = store_.dirstamp(fullpath); - if (conf_.lazy_check && - dirstamp_ >= statbuf->st_mtime && - htype == Scanner::HandleType::EnterNewCur) { - g_debug("skip %s (seems up-to-date)", fullpath.c_str()); - return false; - } + switch (htype) { + case Scanner::HandleType::EnterDir: + case Scanner::HandleType::EnterNewCur: { + // in lazy-mode, we ignore this dir if its dirstamp suggest it + // is up-to-date (this is _not_ always true; hence we call it + // lazy-mode); only for actual message dirs, since the dir + // tstamps may not bubble up. + dirstamp_ = store_.dirstamp(fullpath); + if (conf_.lazy_check && dirstamp_ >= statbuf->st_mtime && + htype == Scanner::HandleType::EnterNewCur) { + g_debug("skip %s (seems up-to-date)", fullpath.c_str()); + return false; + } - // don't index dirs with '.noindex' - auto noindex = ::access((fullpath + "/.noindex").c_str(), F_OK) == 0; - if (noindex) { - g_debug ("skip %s (has .noindex)", fullpath.c_str()); - return false; // don't descend into this dir. - } + // don't index dirs with '.noindex' + auto noindex = ::access((fullpath + "/.noindex").c_str(), F_OK) == 0; + if (noindex) { + g_debug("skip %s (has .noindex)", fullpath.c_str()); + return false; // don't descend into this dir. + } - // don't index dirs with '.noupdate', unless we do a full - // (re)index. - if (!conf_.ignore_noupdate) { - auto noupdate = ::access((fullpath + "/.noupdate").c_str(), F_OK) == 0; - if (noupdate) { - g_debug ("skip %s (has .noupdate)", fullpath.c_str()); - return false; - } - } + // don't index dirs with '.noupdate', unless we do a full + // (re)index. + if (!conf_.ignore_noupdate) { + auto noupdate = ::access((fullpath + "/.noupdate").c_str(), F_OK) == 0; + if (noupdate) { + g_debug("skip %s (has .noupdate)", fullpath.c_str()); + return false; + } + } - g_debug ("process %s", fullpath.c_str()); - return true; + g_debug("process %s", fullpath.c_str()); + return true; + } + case Scanner::HandleType::LeaveDir: { + store_.set_dirstamp(fullpath, ::time(NULL)); + return true; + } - } - case Scanner::HandleType::LeaveDir: { - store_.set_dirstamp(fullpath, ::time(NULL)); - return true; - } + case Scanner::HandleType::File: { + if ((size_t)statbuf->st_size > max_message_size_) { + g_debug("skip %s (too big: %" G_GINT64_FORMAT " bytes)", + fullpath.c_str(), + (gint64)statbuf->st_size); + return false; + } - case Scanner::HandleType::File: { + // if the message is not in the db yet, or not up-to-date, queue + // it for updating/inserting. + if (statbuf->st_mtime <= dirstamp_ && store_.contains_message(fullpath)) { + // g_debug ("skip %s: already up-to-date"); + return false; + } - if ((size_t)statbuf->st_size > max_message_size_) { - g_debug ("skip %s (too big: %" G_GINT64_FORMAT " bytes)", - fullpath.c_str(), (gint64)statbuf->st_size); - return false; - } - - // if the message is not in the db yet, or not up-to-date, queue - // it for updating/inserting. - if (statbuf->st_mtime <= dirstamp_ && - store_.contains_message (fullpath)) { - //g_debug ("skip %s: already up-to-date"); - return false; - } - - fq_.push(std::string{fullpath}); - return true; - } - default: - g_return_val_if_reached (false); - return false; - } + fq_.push(std::string{fullpath}); + return true; + } + default: g_return_val_if_reached(false); return false; + } } void Indexer::Private::maybe_start_worker() { - std::lock_guard wlock{wlock_}; + std::lock_guard wlock{wlock_}; - if (fq_.size() > workers_.size() && workers_.size() < max_workers_) - workers_.emplace_back(std::thread([this]{worker();})); + if (fq_.size() > workers_.size() && workers_.size() < max_workers_) + workers_.emplace_back(std::thread([this] { worker(); })); } void Indexer::Private::worker() { - std::string item; + std::string item; - g_debug ("started worker"); + g_debug("started worker"); - while (state_ == IndexState::Scanning || !fq_.empty()) { + /* note that transaction starting/committing is opportunistic, + * and are NOPs if we are already/not in a transaction */ - if (!fq_.pop (item, 250ms)) - continue; + store_.begin_transaction(); - //g_debug ("popped (n=%zu) path %s", fq_.size(), item.c_str()); - ++progress_.processed; + while (state_ == IndexState::Scanning || !fq_.empty()) { + if (!fq_.pop(item, 250ms)) + continue; - try { - store_.add_message(item); - ++progress_.updated; + // g_debug ("popped (n=%zu) path %s", fq_.size(), item.c_str()); + ++progress_.processed; - } catch (const Mu::Error& er) { - g_warning ("error adding message @ %s: %s", - item.c_str(), er.what()); - } + try { + std::unique_lock lock{lock_}; - maybe_start_worker(); - } + store_.add_message(item); + ++progress_.updated; + + if (progress_.updated % batch_size_ == 0) { + store_.commit_transaction(); + store_.begin_transaction(); + } + + } catch (const Mu::Error& er) { + g_warning("error adding message @ %s: %s", item.c_str(), er.what()); + } + + maybe_start_worker(); + } + + store_.commit_transaction(); } bool Indexer::Private::cleanup() { - g_debug ("starting cleanup"); + g_debug("starting cleanup"); - size_t n{}; - std::vector orphans; // store messages without files. - store_.for_each_message_path([&](Store::Id id, const std::string &path) { + size_t n{}; + std::vector orphans; // store messages without files. + store_.for_each_message_path([&](Store::Id id, const std::string& path) { + ++n; + if (::access(path.c_str(), R_OK) != 0) { + g_debug("cannot read %s (id=%u); queueing for removal from store", + path.c_str(), + id); + orphans.emplace_back(id); + } - ++n; - if (::access(path.c_str(), R_OK) != 0) { - g_debug ("cannot read %s (id=%u); queueing for removal from store", - path.c_str(), id); - orphans.emplace_back(id); - } + return state_ == IndexState::Cleaning; + }); - return state_ == IndexState::Cleaning; - }); + // No need for transactions here, remove_messages does that for us. + if (orphans.empty()) + g_debug("nothing to clean up"); + else { + g_debug("removing up %zu stale message(s) from store", orphans.size()); + store_.remove_messages(orphans); + progress_.removed += orphans.size(); + } - g_debug("remove %zu message(s) from store", orphans.size()); - store_.remove_messages (orphans); - progress_.removed += orphans.size(); - - return true; + return true; } - bool Indexer::Private::start(const Indexer::Config& conf) { - stop(); + stop(); - conf_ = conf; - if (conf_.max_threads == 0) - max_workers_ = std::thread::hardware_concurrency(); - else - max_workers_ = conf.max_threads; + conf_ = conf; + if (conf_.max_threads == 0) + max_workers_ = std::thread::hardware_concurrency(); + else + max_workers_ = conf.max_threads; - g_debug ("starting indexer with <= %zu worker thread(s)", max_workers_); - g_debug ("indexing: %s; clean-up: %s", - conf_.scan ? "yes" : "no", - conf_.cleanup ? "yes" : "no"); + g_debug("starting indexer with <= %zu worker thread(s)", max_workers_); + g_debug("indexing: %s; clean-up: %s", + conf_.scan ? "yes" : "no", + conf_.cleanup ? "yes" : "no"); - workers_.emplace_back(std::thread([this]{worker();})); + workers_.emplace_back(std::thread([this] { worker(); })); - state_.change_to(IndexState::Scanning); - scanner_worker_ = std::thread([this]{ - progress_ = {}; + state_.change_to(IndexState::Scanning); + scanner_worker_ = std::thread([this] { + progress_ = {}; - if (conf_.scan) { - g_debug("starting scanner"); - if (!scanner_.start()) { // blocks. - g_warning ("failed to start scanner"); - goto leave; - } - g_debug ("scanner finished with %zu file(s) in queue", - fq_.size()); - } + if (conf_.scan) { + g_debug("starting scanner"); + if (!scanner_.start()) { // blocks. + g_warning("failed to start scanner"); + goto leave; + } + g_debug("scanner finished with %zu file(s) in queue", fq_.size()); + } + // now there may still be messages in the work queue... + // finish those; this is a bit ugly; perhaps we should + // handle SIGTERM etc. + while (!fq_.empty()) + std::this_thread::sleep_for(100ms); - // now there may still be messages in the work queue... - // finish those; this is a bit ugly; perhaps we should - // handle SIGTERM etc. - while (!fq_.empty()) - std::this_thread::sleep_for(100ms); + if (conf_.cleanup) { + g_debug("starting cleanup"); + state_.change_to(IndexState::Cleaning); + cleanup(); + g_debug("cleanup finished"); + } + leave: + state_.change_to(IndexState::Idle); + }); - if (conf_.cleanup) { - g_debug ("starting cleanup"); - state_.change_to(IndexState::Cleaning); - cleanup(); - g_debug ("cleanup finished"); - } - - store_.commit(); - leave: - state_.change_to(IndexState::Idle); - }); - - g_debug ("started indexer"); - - return true; + g_debug("started indexer"); + return true; } bool Indexer::Private::stop() { - scanner_.stop(); - state_.change_to(IndexState::Idle); + scanner_.stop(); + state_.change_to(IndexState::Idle); - const auto w_n = workers_.size(); + const auto w_n = workers_.size(); - fq_.clear(); - if (scanner_worker_.joinable()) - scanner_worker_.join(); + fq_.clear(); + if (scanner_worker_.joinable()) + scanner_worker_.join(); - for (auto&& w: workers_) - if (w.joinable()) - w.join(); - workers_.clear(); + for (auto&& w : workers_) + if (w.joinable()) + w.join(); + workers_.clear(); - if (w_n > 0) - g_debug ("stopped indexer (joined %zu worker(s))", w_n); + if (w_n > 0) + g_debug("stopped indexer (joined %zu worker(s))", w_n); - return true; + return true; } -Indexer::Indexer (Store& store): - priv_{std::make_unique(store)} -{} +Indexer::Indexer(Store& store) : priv_{std::make_unique(store)} {} Indexer::~Indexer() = default; bool Indexer::start(const Indexer::Config& conf) { - const auto mdir{priv_->store_.metadata().root_maildir}; - if (G_UNLIKELY(access (mdir.c_str(), R_OK) != 0)) { - g_critical("'%s' is not readable: %s", mdir.c_str(), g_strerror (errno)); - return false; - } + const auto mdir{priv_->store_.metadata().root_maildir}; + if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) { + g_critical("'%s' is not readable: %s", mdir.c_str(), g_strerror(errno)); + return false; + } - std::lock_guard l(priv_->lock_); - if (is_running()) - return true; + std::lock_guard l(priv_->lock_); + if (is_running()) + return true; - return priv_->start(conf); + return priv_->start(conf); } bool Indexer::stop() { - std::lock_guard l(priv_->lock_); + std::lock_guard l(priv_->lock_); - if (!is_running()) - return true; + if (!is_running()) + return true; - g_debug ("stopping indexer"); - return priv_->stop(); + g_debug("stopping indexer"); + return priv_->stop(); } bool Indexer::is_running() const { - return !(priv_->state_ == IndexState::Idle) || !priv_->fq_.empty(); + return !(priv_->state_ == IndexState::Idle) || !priv_->fq_.empty(); } Indexer::Progress Indexer::progress() const { - priv_->progress_.running = - priv_->state_ == IndexState::Idle ? false : true; + priv_->progress_.running = priv_->state_ == IndexState::Idle ? false : true; - return priv_->progress_; + return priv_->progress_; } diff --git a/lib/index/mu-indexer.hh b/lib/index/mu-indexer.hh index b2020170..d79ed7cb 100644 --- a/lib/index/mu-indexer.hh +++ b/lib/index/mu-indexer.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2020 Dirk-Jan C. Binnema +** Copyright (C) 2021 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 @@ -29,86 +29,82 @@ class Store; /// An object abstracting the index process. class Indexer { -public: - /** - * Construct an indexer object - * - * @param store the message store to use - */ - Indexer (Store& store); + public: + /** + * Construct an indexer object + * + * @param store the message store to use + */ + Indexer(Store& store); - /** - * DTOR - */ - ~Indexer(); + /** + * DTOR + */ + ~Indexer(); - /// A configuration object for the indexer - struct Config { - bool scan{true}; - /**< scan for new messages */ - bool cleanup{true}; - /**< clean messages no longer in the file system */ - size_t max_threads{}; - /**< maximum # of threads to use */ - bool ignore_noupdate{}; - /**< ignore .noupdate files */ - bool lazy_check{}; - /**< whether to skip directories that don't have a changed - * mtime */ - }; + /// A configuration object for the indexer + struct Config { + bool scan{true}; + /**< scan for new messages */ + bool cleanup{true}; + /**< clean messages no longer in the file system */ + size_t max_threads{}; + /**< maximum # of threads to use */ + bool ignore_noupdate{}; + /**< ignore .noupdate files */ + bool lazy_check{}; + /**< whether to skip directories that don't have a changed + * mtime */ + }; + /** + * Start indexing. If already underway, do nothing. + * + * @param conf a configuration object + * + * @return true if starting worked or an indexing process was already + * underway; false otherwise. + * + */ + bool start(const Config& conf); - /** - * Start indexing. If already underway, do nothing. - * - * @param conf a configuration object - * - * @return true if starting worked or an indexing process was already - * underway; false otherwise. - * - */ - bool start(const Config& conf); + /** + * Stop indexing. If not indexing, do nothing. + * + * + * @return true if we stopped indexing, or indexing was not underway. + * False otherwise. + */ + bool stop(); - /** - * Stop indexing. If not indexing, do nothing. - * - * - * @return true if we stopped indexing, or indexing was not underway. - * False otherwise. - */ - bool stop(); + /** + * Is an indexing process running? + * + * @return true or false. + */ + bool is_running() const; - /** - * Is an indexing process running? - * - * @return true or false. - */ - bool is_running() const; + // Object describing current progress + struct Progress { + bool running{}; /**< Is an index operation in progress? */ + size_t processed{}; /**< Number of messages processed */ + size_t updated{}; /**< Number of messages added/updated to store */ + size_t removed{}; /**< Number of message removed from store */ + }; + /** + * Get an object describing the current progress. The progress object + * describes the most recent indexing job, and is reset up a fresh + * start(). + * + * @return a progress object. + */ + Progress progress() const; - // Object describing current progress - struct Progress { - bool running{}; /**< Is an index operation in progress? */ - size_t processed{}; /**< Number of messages processed */ - size_t updated{}; /**< Number of messages added/updated to store */ - size_t removed{}; /**< Number of message removed from store */ - }; - - /** - * Get an object describing the current progress. The progress object - * describes the most recent indexing job, and is reset up a fresh - * start(). - * - * @return a progress object. - */ - Progress progress() const; - -private: - struct Private; - std::unique_ptr priv_; + private: + struct Private; + std::unique_ptr priv_; }; - - } // namespace Mu #endif /* MU_INDEXER_HH__ */ diff --git a/lib/index/mu-scanner.cc b/lib/index/mu-scanner.cc index dc714c9a..2108b096 100644 --- a/lib/index/mu-scanner.cc +++ b/lib/index/mu-scanner.cc @@ -38,207 +38,202 @@ using namespace Mu; struct Scanner::Private { - Private (const std::string& root_dir, - Scanner::Handler handler): - root_dir_{root_dir}, handler_{handler} { - if (!handler_) - throw Mu::Error{Error::Code::Internal, "missing handler"}; - } - ~Private() { - stop(); - } + Private(const std::string& root_dir, Scanner::Handler handler) + : root_dir_{root_dir}, handler_{handler} + { + if (!handler_) + throw Mu::Error{Error::Code::Internal, "missing handler"}; + } + ~Private() { stop(); } - bool start(); - bool stop(); - bool process_dentry (const std::string& path, struct dirent *dentry, bool is_maildir); - bool process_dir (const std::string& path, bool is_maildir); + bool start(); + bool stop(); + bool process_dentry(const std::string& path, struct dirent* dentry, bool is_maildir); + bool process_dir(const std::string& path, bool is_maildir); - const std::string root_dir_; - const Scanner::Handler handler_; - std::atomic running_{}; - std::mutex lock_; + const std::string root_dir_; + const Scanner::Handler handler_; + std::atomic running_{}; + std::mutex lock_; }; - static bool -is_special_dir (const struct dirent *dentry) +is_special_dir(const struct dirent* dentry) { - const auto d_name{dentry->d_name}; - return d_name[0] == '\0' || - (d_name[1] == '\0' && d_name[0] == '.') || - (d_name[2] == '\0' && d_name[0] == '.' && d_name[1] == '.'); + const auto d_name{dentry->d_name}; + return d_name[0] == '\0' || (d_name[1] == '\0' && d_name[0] == '.') || + (d_name[2] == '\0' && d_name[0] == '.' && d_name[1] == '.'); } static bool -is_new_cur (const char *dirname) +is_new_cur(const char* dirname) { - if (dirname[0] == 'c' && dirname[1] == 'u' && dirname[2] == 'r' && dirname[3] == '\0') - return true; + if (dirname[0] == 'c' && dirname[1] == 'u' && dirname[2] == 'r' && dirname[3] == '\0') + return true; - if (dirname[0] == 'n' && dirname[1] == 'e' && dirname[2] == 'w' && dirname[3] == '\0') - return true; + if (dirname[0] == 'n' && dirname[1] == 'e' && dirname[2] == 'w' && dirname[3] == '\0') + return true; - return false; + return false; } bool -Scanner::Private::process_dentry (const std::string& path, struct dirent *dentry, - bool is_maildir) +Scanner::Private::process_dentry(const std::string& path, struct dirent* dentry, bool is_maildir) { - if (is_special_dir (dentry)) - return true; // ignore. + if (is_special_dir(dentry)) + return true; // ignore. - const auto fullpath{path + "/" + dentry->d_name}; - struct stat statbuf; - if (::stat(fullpath.c_str(), &statbuf) != 0) { - g_warning ("failed to stat %s: %s", fullpath.c_str(), g_strerror(errno)); - return false; - } + const auto fullpath{path + "/" + dentry->d_name}; + struct stat statbuf; + if (::stat(fullpath.c_str(), &statbuf) != 0) { + g_warning("failed to stat %s: %s", fullpath.c_str(), g_strerror(errno)); + return false; + } - if (S_ISDIR(statbuf.st_mode)) { - const auto new_cur = is_new_cur(dentry->d_name); - const auto htype = new_cur ? - Scanner::HandleType::EnterNewCur : - Scanner::HandleType::EnterDir; - const auto res = handler_(fullpath, &statbuf, htype); - if (!res) - return true; // skip + if (S_ISDIR(statbuf.st_mode)) { + const auto new_cur = is_new_cur(dentry->d_name); + const auto htype = new_cur ? Scanner::HandleType::EnterNewCur + : Scanner::HandleType::EnterDir; + const auto res = handler_(fullpath, &statbuf, htype); + if (!res) + return true; // skip - process_dir (fullpath, new_cur); + process_dir(fullpath, new_cur); - return handler_(fullpath, &statbuf, Scanner::HandleType::LeaveDir); + return handler_(fullpath, &statbuf, Scanner::HandleType::LeaveDir); - } else if (S_ISREG(statbuf.st_mode) && is_maildir) - return handler_(fullpath, &statbuf, Scanner::HandleType::File); + } else if (S_ISREG(statbuf.st_mode) && is_maildir) + return handler_(fullpath, &statbuf, Scanner::HandleType::File); - g_debug ("skip %s (neither maildir-file nor directory)", fullpath.c_str()); - return true; + g_debug("skip %s (neither maildir-file nor directory)", fullpath.c_str()); + return true; } - bool -Scanner::Private::process_dir (const std::string& path, bool is_maildir) +Scanner::Private::process_dir(const std::string& path, bool is_maildir) { - const auto dir = opendir (path.c_str()); - if (G_UNLIKELY(!dir)) { - g_warning("failed to scan dir %s: %s", path.c_str(), g_strerror(errno)); - return false; - } + const auto dir = opendir(path.c_str()); + if (G_UNLIKELY(!dir)) { + g_warning("failed to scan dir %s: %s", path.c_str(), g_strerror(errno)); + return false; + } - // TODO: sort dentries by inode order, which makes things faster for extfs. - // see mu-maildir.c + // TODO: sort dentries by inode order, which makes things faster for extfs. + // see mu-maildir.c - while (running_) { - errno = 0; - const auto dentry{readdir(dir)}; + while (running_) { + errno = 0; + const auto dentry{readdir(dir)}; - if (G_LIKELY(dentry)) { - process_dentry (path, dentry, is_maildir); - continue; - } + if (G_LIKELY(dentry)) { + process_dentry(path, dentry, is_maildir); + continue; + } - if (errno != 0) { - g_warning("failed to read %s: %s", path.c_str(), g_strerror(errno)); - continue; - } + if (errno != 0) { + g_warning("failed to read %s: %s", path.c_str(), g_strerror(errno)); + continue; + } - break; - } - closedir (dir); + break; + } + closedir(dir); - return true; + return true; } bool Scanner::Private::start() { - const auto& path{root_dir_}; - if (G_UNLIKELY(path.length() > PATH_MAX)) { - g_warning("path too long"); - return false; - } + const auto& path{root_dir_}; + if (G_UNLIKELY(path.length() > PATH_MAX)) { + g_warning("path too long"); + return false; + } - const auto mode{F_OK | R_OK}; - if (G_UNLIKELY(access (path.c_str(), mode) != 0)) { - g_warning("'%s' is not readable: %s", path.c_str(), g_strerror (errno)); - return false; - } + const auto mode{F_OK | R_OK}; + if (G_UNLIKELY(access(path.c_str(), mode) != 0)) { + g_warning("'%s' is not readable: %s", path.c_str(), g_strerror(errno)); + return false; + } - struct stat statbuf{}; - if (G_UNLIKELY(stat (path.c_str(), &statbuf) != 0)) { - g_warning("'%s' is not stat'able: %s", path.c_str(), g_strerror (errno)); - return false; - } + struct stat statbuf { + }; + if (G_UNLIKELY(stat(path.c_str(), &statbuf) != 0)) { + g_warning("'%s' is not stat'able: %s", path.c_str(), g_strerror(errno)); + return false; + } - if (G_UNLIKELY(!S_ISDIR (statbuf.st_mode))) { - g_warning("'%s' is not a directory", path.c_str()); - return false; - } + if (G_UNLIKELY(!S_ISDIR(statbuf.st_mode))) { + g_warning("'%s' is not a directory", path.c_str()); + return false; + } - running_ = true; - g_debug ("starting scan @ %s", root_dir_.c_str()); + running_ = true; + g_debug("starting scan @ %s", root_dir_.c_str()); - auto basename{g_path_get_basename(root_dir_.c_str())}; - const auto is_maildir = (g_strcmp0(basename, "cur") == 0 || - g_strcmp0(basename,"new") == 0); - g_free(basename); + auto basename{g_path_get_basename(root_dir_.c_str())}; + const auto is_maildir = + (g_strcmp0(basename, "cur") == 0 || g_strcmp0(basename, "new") == 0); + g_free(basename); - const auto start{std::chrono::steady_clock::now()}; - process_dir(root_dir_, is_maildir); - const auto elapsed = std::chrono::steady_clock::now() - start; - g_debug ("finished scan of %s in %" G_GINT64_FORMAT " ms", root_dir_.c_str(), - to_ms(elapsed)); - running_ = false; + const auto start{std::chrono::steady_clock::now()}; + process_dir(root_dir_, is_maildir); + const auto elapsed = std::chrono::steady_clock::now() - start; + g_debug("finished scan of %s in %" G_GINT64_FORMAT " ms", + root_dir_.c_str(), + to_ms(elapsed)); + running_ = false; - return true; + return true; } bool Scanner::Private::stop() { - if (!running_) - return true; // nothing to do + if (!running_) + return true; // nothing to do - g_debug ("stopping scan"); - running_ = false; + g_debug("stopping scan"); + running_ = false; - return true; + return true; } -Scanner::Scanner (const std::string& root_dir, - Scanner::Handler handler): - priv_{std::make_unique(root_dir, handler)} -{} +Scanner::Scanner(const std::string& root_dir, Scanner::Handler handler) + : priv_{std::make_unique(root_dir, handler)} +{ +} Scanner::~Scanner() = default; bool Scanner::start() { - { - std::lock_guard l(priv_->lock_); - if (priv_->running_) - return true; //nothing to do + { + std::lock_guard l(priv_->lock_); + if (priv_->running_) + return true; // nothing to do - priv_->running_ = true; - } + priv_->running_ = true; + } - const auto res = priv_->start(); - priv_->running_ = false; + const auto res = priv_->start(); + priv_->running_ = false; - return res; + return res; } bool Scanner::stop() { - std::lock_guard l(priv_->lock_); + std::lock_guard l(priv_->lock_); - return priv_->stop(); + return priv_->stop(); } bool Scanner::is_running() const { - return priv_->running_; + return priv_->running_; } diff --git a/lib/index/mu-scanner.hh b/lib/index/mu-scanner.hh index 1b0d6c48..c03d94e1 100644 --- a/lib/index/mu-scanner.hh +++ b/lib/index/mu-scanner.hh @@ -41,59 +41,58 @@ namespace Mu { /// - directories '.' and '..' /// class Scanner { -public: - enum struct HandleType { - File, - EnterNewCur, /* cur/ or new/ */ - EnterDir, /* some other directory */ - LeaveDir - }; + public: + enum struct HandleType { + File, + EnterNewCur, /* cur/ or new/ */ + EnterDir, /* some other directory */ + LeaveDir + }; - /// Prototype for a handler function - using Handler = std::function; - /** - * Construct a scanner object for scanning a directory, recursively. - * - * If handler is a directory - * - * - * @param root_dir root dir to start scanning - * @param handler handler function for some direntry - */ - Scanner (const std::string& root_dir, Handler handler); + /// Prototype for a handler function + using Handler = std::function< + bool(const std::string& fullpath, struct stat* statbuf, HandleType htype)>; + /** + * Construct a scanner object for scanning a directory, recursively. + * + * If handler is a directory + * + * + * @param root_dir root dir to start scanning + * @param handler handler function for some direntry + */ + Scanner(const std::string& root_dir, Handler handler); - /** - * DTOR - */ - ~Scanner(); + /** + * DTOR + */ + ~Scanner(); - /** - * Start the scan; this is a blocking call than runs until - * finished or (from another thread) stop() is called. - * - * @return true if starting worked; false otherwise - */ - bool start(); + /** + * Start the scan; this is a blocking call than runs until + * finished or (from another thread) stop() is called. + * + * @return true if starting worked; false otherwise + */ + bool start(); - /** - * Stop the scan - * - * @return true if stopping worked; false otherwi%sse - */ - bool stop(); + /** + * Stop the scan + * + * @return true if stopping worked; false otherwi%sse + */ + bool stop(); - /** - * Is a scan currently running? - * - * @return true or false - */ - bool is_running() const; + /** + * Is a scan currently running? + * + * @return true or false + */ + bool is_running() const; -private: - struct Private; - std::unique_ptr priv_; + private: + struct Private; + std::unique_ptr priv_; }; } // namespace Mu diff --git a/lib/index/test-scanner.cc b/lib/index/test-scanner.cc index a5df4e50..4835aa13 100644 --- a/lib/index/test-scanner.cc +++ b/lib/index/test-scanner.cc @@ -28,39 +28,36 @@ using namespace Mu; - static void -test_scan_maildir () +test_scan_maildir() { allow_warnings(); - Scanner scanner{"/home/djcb/Maildir", - [](const dirent* dentry)->bool { - g_print ("%02x %s\n", dentry->d_type, dentry->d_name); - return true; - }, - [](const std::string& fullpath, const struct stat* statbuf, - auto&& info)->bool { - g_print ("%s %zu\n", fullpath.c_str(), statbuf->st_size); - return true; - } - }; - g_assert_true (scanner.start()); + Scanner scanner{ + "/home/djcb/Maildir", + [](const dirent* dentry) -> bool { + g_print("%02x %s\n", dentry->d_type, dentry->d_name); + return true; + }, + [](const std::string& fullpath, const struct stat* statbuf, auto&& info) -> bool { + g_print("%s %zu\n", fullpath.c_str(), statbuf->st_size); + return true; + }}; + g_assert_true(scanner.start()); - while (scanner.is_running()) { - sleep(1); - } + while (scanner.is_running()) { + sleep(1); + } } int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/utils/scanner/scan-maildir", test_scan_maildir); - - return g_test_run (); + g_test_add_func("/utils/scanner/scan-maildir", test_scan_maildir); + return g_test_run(); } catch (const std::runtime_error& re) { std::cerr << re.what() << "\n"; diff --git a/lib/meson.build b/lib/meson.build index dfb0eead..bd661b4c 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -73,6 +73,7 @@ lib_mu=static_library( gio_dep, gmime_dep, xapian_dep, + guile_dep, config_h_dep, lib_mu_utils_dep, lib_mu_index_dep diff --git a/lib/mu-bookmarks.cc b/lib/mu-bookmarks.cc index 5f2c0ae1..1865b643 100644 --- a/lib/mu-bookmarks.cc +++ b/lib/mu-bookmarks.cc @@ -23,123 +23,114 @@ #define MU_BOOKMARK_GROUP "mu" struct MuBookmarks { - char *_bmpath; - GHashTable *_hash; + char* _bmpath; + GHashTable* _hash; }; - static void -fill_hash (GHashTable *hash, GKeyFile *kfile) +fill_hash(GHashTable* hash, GKeyFile* kfile) { gchar **keys, **cur; - keys = g_key_file_get_keys (kfile, MU_BOOKMARK_GROUP, NULL, NULL); + keys = g_key_file_get_keys(kfile, MU_BOOKMARK_GROUP, NULL, NULL); if (!keys) return; for (cur = keys; *cur; ++cur) { - gchar *val; - val = g_key_file_get_string (kfile, MU_BOOKMARK_GROUP, - *cur, NULL); + gchar* val; + val = g_key_file_get_string(kfile, MU_BOOKMARK_GROUP, *cur, NULL); if (val) - g_hash_table_insert (hash, *cur, val); + g_hash_table_insert(hash, *cur, val); } /* don't use g_strfreev, because we put them in the hash table; * only free the gchar** itself */ - g_free (keys); + g_free(keys); } static GHashTable* -create_hash_from_key_file (const gchar *bmpath) +create_hash_from_key_file(const gchar* bmpath) { - GKeyFile *kfile; - GHashTable *hash; + GKeyFile* kfile; + GHashTable* hash; - kfile = g_key_file_new (); + kfile = g_key_file_new(); - if (!g_key_file_load_from_file (kfile, bmpath, G_KEY_FILE_NONE, NULL)) { - g_key_file_free (kfile); + if (!g_key_file_load_from_file(kfile, bmpath, G_KEY_FILE_NONE, NULL)) { + g_key_file_free(kfile); return NULL; } - hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - fill_hash (hash, kfile); + hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + fill_hash(hash, kfile); - g_key_file_free (kfile); + g_key_file_free(kfile); return hash; } - - MuBookmarks* -mu_bookmarks_new (const gchar *bmpath) +mu_bookmarks_new(const gchar* bmpath) { - MuBookmarks *bookmarks; - GHashTable *hash; + MuBookmarks* bookmarks; + GHashTable* hash; - g_return_val_if_fail (bmpath, NULL); + g_return_val_if_fail(bmpath, NULL); - hash = create_hash_from_key_file (bmpath); + hash = create_hash_from_key_file(bmpath); if (!hash) return NULL; - bookmarks = g_new (MuBookmarks, 1); + bookmarks = g_new(MuBookmarks, 1); - bookmarks->_bmpath = g_strdup (bmpath); + bookmarks->_bmpath = g_strdup(bmpath); bookmarks->_hash = hash; return bookmarks; } - - void -mu_bookmarks_destroy (MuBookmarks *bm) +mu_bookmarks_destroy(MuBookmarks* bm) { if (!bm) return; - g_free (bm->_bmpath); - g_hash_table_destroy (bm->_hash); - g_free (bm); + g_free(bm->_bmpath); + g_hash_table_destroy(bm->_hash); + g_free(bm); } const gchar* -mu_bookmarks_lookup (MuBookmarks *bm, const gchar *name) +mu_bookmarks_lookup(MuBookmarks* bm, const gchar* name) { - g_return_val_if_fail (bm, NULL); - g_return_val_if_fail (name, NULL); + g_return_val_if_fail(bm, NULL); + g_return_val_if_fail(name, NULL); - return (const char*)g_hash_table_lookup (bm->_hash, name); + return (const char*)g_hash_table_lookup(bm->_hash, name); } struct _BMData { MuBookmarksForeachFunc _func; - gpointer _user_data; + gpointer _user_data; }; typedef struct _BMData BMData; - static void -each_bookmark (const gchar* key, const gchar *val, BMData *bmdata) +each_bookmark(const gchar* key, const gchar* val, BMData* bmdata) { - bmdata->_func (key, val, bmdata->_user_data); + bmdata->_func(key, val, bmdata->_user_data); } - void -mu_bookmarks_foreach (MuBookmarks *bm, MuBookmarksForeachFunc func, - gpointer user_data) +mu_bookmarks_foreach(MuBookmarks* bm, MuBookmarksForeachFunc func, gpointer user_data) { BMData bmdata; - g_return_if_fail (bm); - g_return_if_fail (func); + g_return_if_fail(bm); + g_return_if_fail(func); - bmdata._func = func; + bmdata._func = func; bmdata._user_data = user_data; - g_hash_table_foreach (bm->_hash, (GHFunc)each_bookmark, &bmdata); + g_hash_table_foreach(bm->_hash, (GHFunc)each_bookmark, &bmdata); } diff --git a/lib/mu-bookmarks.hh b/lib/mu-bookmarks.hh index a30dceba..a68d23a2 100644 --- a/lib/mu-bookmarks.hh +++ b/lib/mu-bookmarks.hh @@ -32,7 +32,6 @@ */ struct MuBookmarks; - /** * create a new bookmarks object. when it's no longer needed, use * mu_bookmarks_destroy @@ -41,16 +40,14 @@ struct MuBookmarks; * * @return a new BookMarks object, or NULL in case of error */ -MuBookmarks *mu_bookmarks_new (const gchar *bmpath) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +MuBookmarks* mu_bookmarks_new(const gchar* bmpath) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * destroy a bookmarks object * * @param bm a bookmarks object, or NULL */ -void mu_bookmarks_destroy (MuBookmarks *bm); - +void mu_bookmarks_destroy(MuBookmarks* bm); /** * get the value for some bookmark @@ -61,10 +58,9 @@ void mu_bookmarks_destroy (MuBookmarks *bm); * @return the value of the bookmark or NULL in case in error, e.g. if * the bookmark was not found */ -const gchar* mu_bookmarks_lookup (MuBookmarks *bm, const gchar *name); +const gchar* mu_bookmarks_lookup(MuBookmarks* bm, const gchar* name); -typedef void (*MuBookmarksForeachFunc) (const gchar *key, const gchar *val, - gpointer user_data); +typedef void (*MuBookmarksForeachFunc)(const gchar* key, const gchar* val, gpointer user_data); /** * call a function for each bookmark @@ -73,8 +69,7 @@ typedef void (*MuBookmarksForeachFunc) (const gchar *key, const gchar *val, * @param func a callback function to be called for each bookmarks * @param user_data a user pointer passed to the callback */ -void mu_bookmarks_foreach (MuBookmarks *bm, MuBookmarksForeachFunc func, - gpointer user_data); +void mu_bookmarks_foreach(MuBookmarks* bm, MuBookmarksForeachFunc func, gpointer user_data); /** @} */ diff --git a/lib/mu-contacts.cc b/lib/mu-contacts.cc index c027af83..85d719ed 100644 --- a/lib/mu-contacts.cc +++ b/lib/mu-contacts.cc @@ -33,287 +33,285 @@ using namespace Mu; -ContactInfo::ContactInfo (const std::string& _full_address, - const std::string& _email, - const std::string& _name, - bool _personal, - time_t _last_seen, - size_t _freq): - full_address{_full_address}, - email{_email}, - name{_name}, - personal{_personal}, - last_seen{_last_seen}, - freq{_freq}, - tstamp{g_get_monotonic_time()} {} +ContactInfo::ContactInfo(const std::string& _full_address, + const std::string& _email, + const std::string& _name, + bool _personal, + time_t _last_seen, + size_t _freq) + : full_address{_full_address}, email{_email}, name{_name}, personal{_personal}, + last_seen{_last_seen}, freq{_freq}, tstamp{g_get_monotonic_time()} +{ +} struct EmailHash { - std::size_t operator()(const std::string& email) const { - std::size_t djb = 5381; // djb hash - for (const auto c : email) - djb = ((djb << 5) + djb) + g_ascii_tolower(c); - return djb; - } + std::size_t operator()(const std::string& email) const + { + std::size_t djb = 5381; // djb hash + for (const auto c : email) + djb = ((djb << 5) + djb) + g_ascii_tolower(c); + return djb; + } }; struct EmailEqual { - bool operator()(const std::string& email1, const std::string& email2) const { - return g_ascii_strcasecmp(email1.c_str(), email2.c_str()) == 0; - } + bool operator()(const std::string& email1, const std::string& email2) const + { + return g_ascii_strcasecmp(email1.c_str(), email2.c_str()) == 0; + } }; struct ContactInfoHash { - std::size_t operator()(const ContactInfo& ci) const { - std::size_t djb = 5381; // djb hash - for (const auto c : ci.email) - djb = ((djb << 5) + djb) + g_ascii_tolower(c); - return djb; - } + std::size_t operator()(const ContactInfo& ci) const + { + std::size_t djb = 5381; // djb hash + for (const auto c : ci.email) + djb = ((djb << 5) + djb) + g_ascii_tolower(c); + return djb; + } }; struct ContactInfoEqual { - bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const { - return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) == 0; - } + bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const + { + return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) == 0; + } }; constexpr auto RecentOffset{15 * 24 * 3600}; struct ContactInfoLessThan { + ContactInfoLessThan() : recently_{::time({}) - RecentOffset} {} - ContactInfoLessThan(): recently_{::time({}) - RecentOffset} {} + bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const + { + if (ci1.personal != ci2.personal) + return ci1.personal; // personal comes first - bool operator()(const Mu::ContactInfo& ci1, const Mu::ContactInfo& ci2) const { + if ((ci1.last_seen > recently_) != (ci2.last_seen > recently_)) + return ci1.last_seen > ci2.last_seen; - if (ci1.personal != ci2.personal) - return ci1.personal; // personal comes first + if (ci1.freq != ci2.freq) // more frequent comes first + return ci1.freq > ci2.freq; - if ((ci1.last_seen > recently_) != (ci2.last_seen > recently_)) - return ci1.last_seen > ci2.last_seen; - - if (ci1.freq != ci2.freq) // more frequent comes first - return ci1.freq > ci2.freq; - - return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) < 0; - } - // only sort recently seen contacts by recency; approx 15 days. - // this changes during the lifetime, but that's all fine. - const time_t recently_; + return g_ascii_strcasecmp(ci1.email.c_str(), ci2.email.c_str()) < 0; + } + // only sort recently seen contacts by recency; approx 15 days. + // this changes during the lifetime, but that's all fine. + const time_t recently_; }; using ContactUMap = std::unordered_map; -//using ContactUSet = std::unordered_set; -using ContactSet = std::set, ContactInfoLessThan>; +// using ContactUSet = std::unordered_set; +using ContactSet = std::set, ContactInfoLessThan>; struct Contacts::Private { - Private(const std::string& serialized, - const StringVec& personal): - contacts_{deserialize(serialized)} { - make_personal(personal); - } + Private(const std::string& serialized, const StringVec& personal) + : contacts_{deserialize(serialized)} + { + make_personal(personal); + } - void make_personal(const StringVec& personal); - ContactUMap deserialize(const std::string&) const; - std::string serialize() const; + void make_personal(const StringVec& personal); + ContactUMap deserialize(const std::string&) const; + std::string serialize() const; - ContactUMap contacts_; - std::mutex mtx_; + ContactUMap contacts_; + std::mutex mtx_; - StringVec personal_plain_; - std::vector personal_rx_; + StringVec personal_plain_; + std::vector personal_rx_; }; constexpr auto Separator = "\xff"; // Invalid in UTF-8 void -Contacts::Private::make_personal (const StringVec& personal) +Contacts::Private::make_personal(const StringVec& personal) { - for (auto&& p: personal) { + for (auto&& p : personal) { + if (p.empty()) + continue; // invalid - if (p.empty()) - continue; // invalid + if (p.size() < 2 || p.at(0) != '/' || p.at(p.length() - 1) != '/') + personal_plain_.emplace_back(p); // normal address + else { + // a regex pattern. + try { + const auto rxstr{p.substr(1, p.length() - 2)}; + personal_rx_.emplace_back(std::regex( + rxstr, + std::regex::basic | std::regex::optimize | std::regex::icase)); - if (p.size() < 2 || p.at(0) != '/' || p.at(p.length() - 1) != '/') - personal_plain_.emplace_back(p); // normal address - else { - // a regex pattern. - try { - const auto rxstr{p.substr(1, p.length()-2)}; - personal_rx_.emplace_back( - std::regex(rxstr, - std::regex::basic | - std::regex::optimize | - std::regex::icase)); - - } catch (const std::regex_error& rex) { - g_warning ("invalid personal address regexp '%s': %s", - p.c_str(), rex.what()); - } - } - } + } catch (const std::regex_error& rex) { + g_warning("invalid personal address regexp '%s': %s", + p.c_str(), + rex.what()); + } + } + } } ContactUMap Contacts::Private::deserialize(const std::string& serialized) const { - ContactUMap contacts; - std::stringstream ss{serialized, std::ios_base::in}; - std::string line; + ContactUMap contacts; + std::stringstream ss{serialized, std::ios_base::in}; + std::string line; - while (getline (ss, line)) { + while (getline(ss, line)) { + const auto parts = Mu::split(line, Separator); + if (G_UNLIKELY(parts.size() != 6)) { + g_warning("error: '%s'", line.c_str()); + continue; + } - const auto parts = Mu::split (line, Separator); - if (G_UNLIKELY(parts.size() != 6)) { - g_warning ("error: '%s'", line.c_str()); - continue; - } + ContactInfo ci(std::move(parts[0]), // full address + parts[1], // email + std::move(parts[2]), // name + parts[3][0] == '1' ? true : false, // personal + (time_t)g_ascii_strtoll(parts[4].c_str(), NULL, 10), // last_seen + (std::size_t)g_ascii_strtoll(parts[5].c_str(), NULL, 10)); // freq - ContactInfo ci(std::move(parts[0]), // full address - parts[1], // email - std::move(parts[2]), // name - parts[3][0] == '1' ? true : false, // personal - (time_t)g_ascii_strtoll(parts[4].c_str(), NULL, 10), // last_seen - (std::size_t)g_ascii_strtoll(parts[5].c_str(), NULL, 10)); // freq + contacts.emplace(std::move(parts[1]), std::move(ci)); + } - contacts.emplace(std::move(parts[1]), std::move(ci)); - } - - return contacts; + return contacts; } - -Contacts::Contacts (const std::string& serialized, const StringVec& personal) : - priv_{std::make_unique(serialized, personal)} -{} +Contacts::Contacts(const std::string& serialized, const StringVec& personal) + : priv_{std::make_unique(serialized, personal)} +{ +} Contacts::~Contacts() = default; std::string Contacts::serialize() const { - std::lock_guard l_{priv_->mtx_}; - std::string s; + std::lock_guard l_{priv_->mtx_}; + std::string s; - for (auto& item: priv_->contacts_) { - const auto& ci{item.second}; - s += Mu::format("%s%s" - "%s%s" - "%s%s" - "%d%s" - "%" G_GINT64_FORMAT "%s" - "%" G_GINT64_FORMAT "\n", - ci.full_address.c_str(), Separator, - ci.email.c_str(), Separator, - ci.name.c_str(), Separator, - ci.personal ? 1 : 0, Separator, - (gint64)ci.last_seen, Separator, - (gint64)ci.freq); - } + for (auto& item : priv_->contacts_) { + const auto& ci{item.second}; + s += Mu::format("%s%s" + "%s%s" + "%s%s" + "%d%s" + "%" G_GINT64_FORMAT "%s" + "%" G_GINT64_FORMAT "\n", + ci.full_address.c_str(), + Separator, + ci.email.c_str(), + Separator, + ci.name.c_str(), + Separator, + ci.personal ? 1 : 0, + Separator, + (gint64)ci.last_seen, + Separator, + (gint64)ci.freq); + } - return s; + return s; } const ContactInfo -Contacts::add (ContactInfo&& ci) +Contacts::add(ContactInfo&& ci) { - std::lock_guard l_{priv_->mtx_}; + std::lock_guard l_{priv_->mtx_}; - auto it = priv_->contacts_.find(ci.email); + auto it = priv_->contacts_.find(ci.email); - if (it == priv_->contacts_.end()) { // completely new contact + if (it == priv_->contacts_.end()) { // completely new contact - ci.name = Mu::remove_ctrl(ci.name); - ci.full_address = remove_ctrl(ci.full_address); + ci.name = Mu::remove_ctrl(ci.name); + ci.full_address = remove_ctrl(ci.full_address); - auto email{ci.email}; - return priv_->contacts_.emplace(ContactUMap::value_type(email, std::move(ci))).first->second; + auto email{ci.email}; + return priv_->contacts_.emplace(ContactUMap::value_type(email, std::move(ci))) + .first->second; - } else { // existing contact. - auto& ci_existing{it->second}; - ++ci_existing.freq; + } else { // existing contact. + auto& ci_existing{it->second}; + ++ci_existing.freq; - if (ci.last_seen > ci_existing.last_seen) { // update. + if (ci.last_seen > ci_existing.last_seen) { // update. - ci_existing.email = std::move(ci.email); - ci_existing.name = Mu::remove_ctrl(ci.name); - ci_existing.full_address = Mu::remove_ctrl(ci.full_address); + ci_existing.email = std::move(ci.email); + ci_existing.name = Mu::remove_ctrl(ci.name); + ci_existing.full_address = Mu::remove_ctrl(ci.full_address); - ci_existing.tstamp = g_get_monotonic_time(); - ci_existing.last_seen = ci.last_seen; - } + ci_existing.tstamp = g_get_monotonic_time(); + ci_existing.last_seen = ci.last_seen; + } - return std::move(ci); - } + return std::move(ci); + } } - const ContactInfo* -Contacts::_find (const std::string& email) const +Contacts::_find(const std::string& email) const { - std::lock_guard l_{priv_->mtx_}; + std::lock_guard l_{priv_->mtx_}; - const auto it = priv_->contacts_.find(email); - if (it == priv_->contacts_.end()) - return {}; - else - return &it->second; + const auto it = priv_->contacts_.find(email); + if (it == priv_->contacts_.end()) + return {}; + else + return &it->second; } - void Contacts::clear() { - std::lock_guard l_{priv_->mtx_}; + std::lock_guard l_{priv_->mtx_}; - priv_->contacts_.clear(); + priv_->contacts_.clear(); } - std::size_t Contacts::size() const { - std::lock_guard l_{priv_->mtx_}; + std::lock_guard l_{priv_->mtx_}; - return priv_->contacts_.size(); + return priv_->contacts_.size(); } - void Contacts::for_each(const EachContactFunc& each_contact) const { - std::lock_guard l_{priv_->mtx_}; + std::lock_guard l_{priv_->mtx_}; - if (!each_contact) - return; // nothing to do + if (!each_contact) + return; // nothing to do - // first sort them for 'rank' - ContactSet sorted; - for (const auto& item: priv_->contacts_) - sorted.emplace(item.second); + // first sort them for 'rank' + ContactSet sorted; + for (const auto& item : priv_->contacts_) + sorted.emplace(item.second); - for (const auto& ci: sorted) - each_contact (ci); + for (const auto& ci : sorted) + each_contact(ci); } bool Contacts::is_personal(const std::string& addr) const { - for (auto&& p: priv_->personal_plain_) - if (g_ascii_strcasecmp(addr.c_str(), p.c_str()) == 0) - return true; + for (auto&& p : priv_->personal_plain_) + if (g_ascii_strcasecmp(addr.c_str(), p.c_str()) == 0) + return true; - for (auto&& rx: priv_->personal_rx_) { - std::smatch m; // perhaps cache addr in personal_plain_? - if (std::regex_match(addr, m, rx)) - return true; - } + for (auto&& rx : priv_->personal_rx_) { + std::smatch m; // perhaps cache addr in personal_plain_? + if (std::regex_match(addr, m, rx)) + return true; + } - return false; + return false; } - #ifdef BUILD_TESTS /* - * Tests. + * Tests. * */ @@ -322,83 +320,84 @@ Contacts::is_personal(const std::string& addr) const static void test_mu_contacts_01() { - Mu::Contacts contacts (""); + Mu::Contacts contacts(""); - g_assert_true (contacts.empty()); - g_assert_cmpuint (contacts.size(), ==, 0); + g_assert_true(contacts.empty()); + g_assert_cmpuint(contacts.size(), ==, 0); - contacts.add(Mu::ContactInfo ("Foo ", - "foo.bar@example.com", "Foo", false, 12345)); - g_assert_false (contacts.empty()); - g_assert_cmpuint (contacts.size(), ==, 1); + contacts.add(Mu::ContactInfo("Foo ", + "foo.bar@example.com", + "Foo", + false, + 12345)); + g_assert_false(contacts.empty()); + g_assert_cmpuint(contacts.size(), ==, 1); - contacts.add(Mu::ContactInfo ("Cuux ", - "cuux@example.com", "Cuux", false, 54321)); + contacts.add(Mu::ContactInfo("Cuux ", + "cuux@example.com", + "Cuux", + false, + 54321)); - g_assert_cmpuint (contacts.size(), ==, 2); + g_assert_cmpuint(contacts.size(), ==, 2); - contacts.add(Mu::ContactInfo ("foo.bar@example.com", - "foo.bar@example.com", "Foo", false, 77777)); - g_assert_cmpuint (contacts.size(), ==, 2); + contacts.add( + Mu::ContactInfo("foo.bar@example.com", "foo.bar@example.com", "Foo", false, 77777)); + g_assert_cmpuint(contacts.size(), ==, 2); - contacts.add(Mu::ContactInfo ("Foo.Bar@Example.Com", - "Foo.Bar@Example.Com", "Foo", false, 88888)); - g_assert_cmpuint (contacts.size(), ==, 2); - // note: replaces first. + contacts.add( + Mu::ContactInfo("Foo.Bar@Example.Com", "Foo.Bar@Example.Com", "Foo", false, 88888)); + g_assert_cmpuint(contacts.size(), ==, 2); + // note: replaces first. - { - const auto info = contacts._find("bla@example.com"); - g_assert_false (info); - } + { + const auto info = contacts._find("bla@example.com"); + g_assert_false(info); + } - { - const auto info = contacts._find("foo.BAR@example.com"); - g_assert_true (info); + { + const auto info = contacts._find("foo.BAR@example.com"); + g_assert_true(info); - g_assert_cmpstr(info->email.c_str(), ==, "Foo.Bar@Example.Com"); - } + g_assert_cmpstr(info->email.c_str(), ==, "Foo.Bar@Example.Com"); + } - contacts.clear(); - g_assert_true (contacts.empty()); - g_assert_cmpuint (contacts.size(), ==, 0); + contacts.clear(); + g_assert_true(contacts.empty()); + g_assert_cmpuint(contacts.size(), ==, 0); } static void test_mu_contacts_02() { - Mu::StringVec personal = { - "foo@example.com", - "bar@cuux.org", - "/bar-.*@fnorb.f./" - }; - Mu::Contacts contacts{"", personal}; + Mu::StringVec personal = {"foo@example.com", "bar@cuux.org", "/bar-.*@fnorb.f./"}; + Mu::Contacts contacts{"", personal}; - g_assert_true (contacts.is_personal("foo@example.com")); - g_assert_true (contacts.is_personal("Bar@CuuX.orG")); - g_assert_true (contacts.is_personal("bar-123abc@fnorb.fi")); - g_assert_true (contacts.is_personal("bar-zzz@fnorb.fr")); + g_assert_true(contacts.is_personal("foo@example.com")); + g_assert_true(contacts.is_personal("Bar@CuuX.orG")); + g_assert_true(contacts.is_personal("bar-123abc@fnorb.fi")); + g_assert_true(contacts.is_personal("bar-zzz@fnorb.fr")); - g_assert_false (contacts.is_personal("foo@bar.com")); - g_assert_false (contacts.is_personal("BÂr@CuuX.orG")); - g_assert_false (contacts.is_personal("bar@fnorb.fi")); - g_assert_false (contacts.is_personal("bar-zzz@fnorb.xr")); + g_assert_false(contacts.is_personal("foo@bar.com")); + g_assert_false(contacts.is_personal("BÂr@CuuX.orG")); + g_assert_false(contacts.is_personal("bar@fnorb.fi")); + g_assert_false(contacts.is_personal("bar-zzz@fnorb.xr")); } - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/mu-contacts/01", test_mu_contacts_01); - g_test_add_func ("/mu-contacts/02", test_mu_contacts_02); + g_test_add_func("/mu-contacts/01", test_mu_contacts_01); + g_test_add_func("/mu-contacts/02", test_mu_contacts_02); - g_log_set_handler (NULL, - (GLogLevelFlags) - (G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - return g_test_run (); + return g_test_run(); } #endif /*BUILD_TESTS*/ diff --git a/lib/mu-contacts.hh b/lib/mu-contacts.hh index 565a4fad..f80b2cd2 100644 --- a/lib/mu-contacts.hh +++ b/lib/mu-contacts.hh @@ -35,126 +35,124 @@ namespace Mu { /// Data-structure representing information about some contact. struct ContactInfo { - /** - * Construct a new ContactInfo - * - * @param _full_address the full email address + name. - * @param _email email address - * @param _name name or empty - * @param _personal is this a personal contact? - * @param _last_seen when was this contact last seen? - * @param _freq how often was this contact seen? - */ - ContactInfo (const std::string& _full_address, - const std::string& _email, - const std::string& _name, - bool personal, - time_t _last_seen, - size_t freq=1); + /** + * Construct a new ContactInfo + * + * @param _full_address the full email address + name. + * @param _email email address + * @param _name name or empty + * @param _personal is this a personal contact? + * @param _last_seen when was this contact last seen? + * @param _freq how often was this contact seen? + */ + ContactInfo(const std::string& _full_address, + const std::string& _email, + const std::string& _name, + bool personal, + time_t _last_seen, + size_t freq = 1); - std::string full_address; /**< Full name */ - std::string email; /**< email address */ - std::string name; /**< name (or empty) */ - bool personal{}; /**< is this a personal contact? */ - time_t last_seen{}; /**< when was this contact last seen? */ - std::size_t freq{}; /**< how often was this contact seen? */ + std::string full_address; /**< Full name */ + std::string email; /**< email address */ + std::string name; /**< name (or empty) */ + bool personal{}; /**< is this a personal contact? */ + time_t last_seen{}; /**< when was this contact last seen? */ + std::size_t freq{}; /**< how often was this contact seen? */ - int64_t tstamp{}; /**< Time-stamp, as per g_get_monotonic_time */ + int64_t tstamp{}; /**< Time-stamp, as per g_get_monotonic_time */ }; /// All contacts class Contacts { -public: - /** - * Construct a new contacts objects - * - * @param serialized serialized contacts - * @param personal personal addresses - */ - Contacts (const std::string& serialized = "", - const StringVec& personal={}); + public: + /** + * Construct a new contacts objects + * + * @param serialized serialized contacts + * @param personal personal addresses + */ + Contacts(const std::string& serialized = "", const StringVec& personal = {}); - /** - * DTOR - * - */ - ~Contacts (); + /** + * DTOR + * + */ + ~Contacts(); - /** - * Add a contact - * - * @param ci A contact-info object - * - * @return the inserted / updated / washed contact info. Note that - * this is return _as copy_ to make it thread-safe. - */ - const ContactInfo add(ContactInfo&& ci); + /** + * Add a contact + * + * @param ci A contact-info object + * + * @return the inserted / updated / washed contact info. Note that + * this is return _as copy_ to make it thread-safe. + */ + const ContactInfo add(ContactInfo&& ci); - /** - * Clear all contacts - * - */ - void clear(); + /** + * Clear all contacts + * + */ + void clear(); - /** - * Get the number of contacts - * + /** + * Get the number of contacts + * - * @return number of contacts - */ - std::size_t size() const; + * @return number of contacts + */ + std::size_t size() const; - /** - * Are there no contacts? - * - * @return true or false - */ - bool empty() const { return size() == 0; } + /** + * Are there no contacts? + * + * @return true or false + */ + bool empty() const { return size() == 0; } - /** - * Get the contacts, serialized. - * - * @return serialized contacts - */ - std::string serialize() const; + /** + * Get the contacts, serialized. + * + * @return serialized contacts + */ + std::string serialize() const; + /** + * Does this look like a 'personal' address? + * + * @param addr some e-mail address + * + * @return true or false + */ + bool is_personal(const std::string& addr) const; - /** - * Does this look like a 'personal' address? - * - * @param addr some e-mail address - * - * @return true or false - */ - bool is_personal(const std::string& addr) const; + /** + * Find a contact based on the email address. This is not safe, since + * the returned ptr can be invalidated at any time; only for unit-tests. + * + * @param email email address + * + * @return contact info, or {} if not found + */ + const ContactInfo* _find(const std::string& email) const; - /** - * Find a contact based on the email address. This is not safe, since - * the returned ptr can be invalidated at any time; only for unit-tests. - * - * @param email email address - * - * @return contact info, or {} if not found - */ - const ContactInfo* _find (const std::string& email) const; + /** + * Prototype for a callable that receives a contact + * + * @param contact some contact + */ + using EachContactFunc = std::function; - /** - * Prototype for a callable that receives a contact - * - * @param contact some contact - */ - using EachContactFunc = std::function; + /** + * Invoke some callable for each contact, in order of rank. + * + * @param each_contact + */ + void for_each(const EachContactFunc& each_contact) const; - /** - * Invoke some callable for each contact, in order of rank. - * - * @param each_contact - */ - void for_each (const EachContactFunc& each_contact) const; - -private: - struct Private; - std::unique_ptr priv_; + private: + struct Private; + std::unique_ptr priv_; }; } // namespace Mu diff --git a/lib/mu-data.hh b/lib/mu-data.hh index 25d3634a..d5d91a06 100644 --- a/lib/mu-data.hh +++ b/lib/mu-data.hh @@ -24,7 +24,7 @@ #include #include -#include +#include namespace Mu { @@ -34,17 +34,18 @@ struct Data { enum class Type { Value, Range }; virtual ~Data() = default; - Type type; /**< type of data */ - std::string field; /**< full name of the field */ - std::string prefix; /**< Xapian prefix for thef field */ - unsigned id; /**< Xapian value no for the field */ + Type type; /**< type of data */ + std::string field; /**< full name of the field */ + std::string prefix; /**< Xapian prefix for thef field */ + unsigned id; /**< Xapian value no for the field */ -protected: - Data (Type _type, const std::string& _field, const std::string& _prefix, - unsigned _id): type(_type), field(_field), prefix(_prefix), id(_id) {} + protected: + Data(Type _type, const std::string& _field, const std::string& _prefix, unsigned _id) + : type(_type), field(_field), prefix(_prefix), id(_id) + { + } }; - /** * operator<< * @@ -54,7 +55,7 @@ protected: * @return the updated output stream */ inline std::ostream& -operator<< (std::ostream& os, Data::Type t) +operator<<(std::ostream& os, Data::Type t) { switch (t) { case Data::Type::Value: os << "value"; break; @@ -64,11 +65,10 @@ operator<< (std::ostream& os, Data::Type t) return os; } - /** * Range type -- [a..b] */ -struct Range: public Data { +struct Range : public Data { /** * Construct a range * @@ -78,23 +78,26 @@ struct Range: public Data { * @param _lower lower bound * @param _upper upper bound */ - Range (const std::string& _field, const std::string& _prefix, - unsigned _id, - const std::string& _lower,const std::string& _upper): + Range(const std::string& _field, + const std::string& _prefix, + unsigned _id, + const std::string& _lower, + const std::string& _upper) + : - Data(Data::Type::Range, _field, _prefix, _id), - lower(_lower), upper(_upper) {} + Data(Data::Type::Range, _field, _prefix, _id), lower(_lower), upper(_upper) + { + } - std::string lower; /**< lower bound */ - std::string upper; /**< upper bound */ + std::string lower; /**< lower bound */ + std::string upper; /**< upper bound */ }; - /** * Basic value * */ -struct Value: public Data { +struct Value : public Data { /** * Construct a Value * @@ -103,16 +106,19 @@ struct Value: public Data { * @param _id xapian value number * @param _value the value */ - Value (const std::string& _field, const std::string& _prefix, - unsigned _id, const std::string& _value, bool _phrase = false): - Data(Value::Type::Value, _field, _prefix, _id), - value(_value), phrase(_phrase) {} + Value(const std::string& _field, + const std::string& _prefix, + unsigned _id, + const std::string& _value, + bool _phrase = false) + : Data(Value::Type::Value, _field, _prefix, _id), value(_value), phrase(_phrase) + { + } - std::string value; /**< the value */ - bool phrase; + std::string value; /**< the value */ + bool phrase; }; - /** * operator<< * @@ -122,28 +128,24 @@ struct Value: public Data { * @return the updated output stream */ inline std::ostream& -operator<< (std::ostream& os, const std::unique_ptr& v) +operator<<(std::ostream& os, const std::unique_ptr& v) { switch (v->type) { case Data::Type::Value: { - const auto bval = dynamic_cast (v.get()); - os << ' ' << quote(v->field) << ' ' - << quote(utf8_flatten(bval->value)); + const auto bval = dynamic_cast(v.get()); + os << ' ' << quote(v->field) << ' ' << quote(utf8_flatten(bval->value)); if (bval->phrase) os << " (ph)"; break; } case Data::Type::Range: { - const auto rval = dynamic_cast (v.get()); - os << ' ' << quote(v->field) << ' ' - << quote(rval->lower) << ' ' + const auto rval = dynamic_cast(v.get()); + os << ' ' << quote(v->field) << ' ' << quote(rval->lower) << ' ' << quote(rval->upper); break; } - default: - os << "unexpected type"; - break; + default: os << "unexpected type"; break; } return os; @@ -151,5 +153,4 @@ operator<< (std::ostream& os, const std::unique_ptr& v) } // namespace Mu - #endif /* __DATA_HH__ */ diff --git a/lib/mu-flags.cc b/lib/mu-flags.cc index 66626d18..00d80998 100644 --- a/lib/mu-flags.cc +++ b/lib/mu-flags.cc @@ -23,132 +23,120 @@ using namespace Mu; struct FlagInfo { - MuFlags flag; - char kar; - const char *name; - MuFlagType flag_type; + MuFlags flag; + char kar; + const char* name; + MuFlagType flag_type; }; static const FlagInfo FLAG_INFO[] = { - /* NOTE: order of this is significant, due to optimizations - * below */ + /* NOTE: order of this is significant, due to optimizations + * below */ - { MU_FLAG_DRAFT, 'D', "draft", MU_FLAG_TYPE_MAILFILE }, - { MU_FLAG_FLAGGED, 'F', "flagged", MU_FLAG_TYPE_MAILFILE }, - { MU_FLAG_PASSED, 'P', "passed", MU_FLAG_TYPE_MAILFILE }, - { MU_FLAG_REPLIED, 'R', "replied", MU_FLAG_TYPE_MAILFILE }, - { MU_FLAG_SEEN, 'S', "seen", MU_FLAG_TYPE_MAILFILE }, - { MU_FLAG_TRASHED, 'T', "trashed", MU_FLAG_TYPE_MAILFILE }, + {MU_FLAG_DRAFT, 'D', "draft", MU_FLAG_TYPE_MAILFILE}, + {MU_FLAG_FLAGGED, 'F', "flagged", MU_FLAG_TYPE_MAILFILE}, + {MU_FLAG_PASSED, 'P', "passed", MU_FLAG_TYPE_MAILFILE}, + {MU_FLAG_REPLIED, 'R', "replied", MU_FLAG_TYPE_MAILFILE}, + {MU_FLAG_SEEN, 'S', "seen", MU_FLAG_TYPE_MAILFILE}, + {MU_FLAG_TRASHED, 'T', "trashed", MU_FLAG_TYPE_MAILFILE}, - { MU_FLAG_NEW, 'N', "new", MU_FLAG_TYPE_MAILDIR }, + {MU_FLAG_NEW, 'N', "new", MU_FLAG_TYPE_MAILDIR}, - { MU_FLAG_SIGNED, 'z', "signed", MU_FLAG_TYPE_CONTENT }, - { MU_FLAG_ENCRYPTED, 'x', "encrypted", MU_FLAG_TYPE_CONTENT }, - { MU_FLAG_HAS_ATTACH, 'a', "attach", MU_FLAG_TYPE_CONTENT }, - { MU_FLAG_LIST, 'l', "list", MU_FLAG_TYPE_CONTENT }, - - - { MU_FLAG_UNREAD, 'u', "unread", MU_FLAG_TYPE_PSEUDO } -}; + {MU_FLAG_SIGNED, 'z', "signed", MU_FLAG_TYPE_CONTENT}, + {MU_FLAG_ENCRYPTED, 'x', "encrypted", MU_FLAG_TYPE_CONTENT}, + {MU_FLAG_HAS_ATTACH, 'a', "attach", MU_FLAG_TYPE_CONTENT}, + {MU_FLAG_LIST, 'l', "list", MU_FLAG_TYPE_CONTENT}, + {MU_FLAG_UNREAD, 'u', "unread", MU_FLAG_TYPE_PSEUDO}}; MuFlagType -Mu::mu_flag_type (MuFlags flag) +Mu::mu_flag_type(MuFlags flag) { unsigned u; - for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) if (FLAG_INFO[u].flag == flag) return FLAG_INFO[u].flag_type; return MU_FLAG_TYPE_INVALID; } - char -Mu::mu_flag_char (MuFlags flag) +Mu::mu_flag_char(MuFlags flag) { unsigned u; - for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) if (FLAG_INFO[u].flag == flag) return FLAG_INFO[u].kar; return 0; } - MuFlags -Mu::mu_flag_char_from_name (const char *str) +Mu::mu_flag_char_from_name(const char* str) { unsigned u; - g_return_val_if_fail (str, MU_FLAG_INVALID); + g_return_val_if_fail(str, MU_FLAG_INVALID); - for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) if (g_strcmp0(FLAG_INFO[u].name, str) == 0) return (MuFlags)FLAG_INFO[u].kar; return (MuFlags)0; } - static MuFlags -mu_flag_from_char (char kar) +mu_flag_from_char(char kar) { unsigned u; - for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) if (FLAG_INFO[u].kar == kar) return FLAG_INFO[u].flag; return MU_FLAG_INVALID; } - const char* -Mu::mu_flag_name (MuFlags flag) +Mu::mu_flag_name(MuFlags flag) { unsigned u; - for (u = 0; u != G_N_ELEMENTS (FLAG_INFO); ++u) + for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) if (FLAG_INFO[u].flag == flag) return FLAG_INFO[u].name; return NULL; } - const char* -Mu::mu_flags_to_str_s (MuFlags flags, MuFlagType types) +Mu::mu_flags_to_str_s(MuFlags flags, MuFlagType types) { - unsigned u,v; + unsigned u, v; static char str[sizeof(FLAG_INFO) + 1]; for (u = 0, v = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) - if (flags & FLAG_INFO[u].flag && - types & FLAG_INFO[u].flag_type) + if (flags & FLAG_INFO[u].flag && types & FLAG_INFO[u].flag_type) str[v++] = FLAG_INFO[u].kar; str[v] = '\0'; return str; } - MuFlags -Mu::mu_flags_from_str (const char *str, MuFlagType types, - gboolean ignore_invalid) +Mu::mu_flags_from_str(const char* str, MuFlagType types, gboolean ignore_invalid) { - const char *cur; - MuFlags flag; + const char* cur; + MuFlags flag; - g_return_val_if_fail (str, MU_FLAG_INVALID); + g_return_val_if_fail(str, MU_FLAG_INVALID); for (cur = str, flag = MU_FLAG_NONE; *cur; ++cur) { - MuFlags f; - f = mu_flag_from_char (*cur); + f = mu_flag_from_char(*cur); if (f == MU_FLAG_INVALID) { if (ignore_invalid) @@ -156,77 +144,68 @@ Mu::mu_flags_from_str (const char *str, MuFlagType types, return MU_FLAG_INVALID; } - if (mu_flag_type (f) & types) + if (mu_flag_type(f) & types) flag |= f; } return flag; } - - char* -Mu::mu_flags_custom_from_str (const char *str) +Mu::mu_flags_custom_from_str(const char* str) { - char *custom; + char* custom; const char* cur; - unsigned u; + unsigned u; - g_return_val_if_fail (str, NULL); + g_return_val_if_fail(str, NULL); for (cur = str, u = 0, custom = NULL; *cur; ++cur) { - MuFlags flag; - flag = mu_flag_from_char (*cur); + flag = mu_flag_from_char(*cur); /* if it's a valid file flag, ignore it */ - if (flag != MU_FLAG_INVALID && - mu_flag_type (flag) == MU_FLAG_TYPE_MAILFILE) + if (flag != MU_FLAG_INVALID && mu_flag_type(flag) == MU_FLAG_TYPE_MAILFILE) continue; /* otherwise, add it to our custom string */ if (!custom) - custom = g_new0 (char, strlen(str) + 1); + custom = g_new0(char, strlen(str) + 1); custom[u++] = *cur; } return custom; } - - void -Mu::mu_flags_foreach (MuFlagsForeachFunc func, gpointer user_data) +Mu::mu_flags_foreach(MuFlagsForeachFunc func, gpointer user_data) { unsigned u; - g_return_if_fail (func); + g_return_if_fail(func); for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u) - func (FLAG_INFO[u].flag, user_data); + func(FLAG_INFO[u].flag, user_data); } - MuFlags -Mu::mu_flags_from_str_delta (const char *str, MuFlags oldflags, - MuFlagType types) +Mu::mu_flags_from_str_delta(const char* str, MuFlags oldflags, MuFlagType types) { - const char *cur; - MuFlags newflags; + const char* cur; + MuFlags newflags; - g_return_val_if_fail (str, MU_FLAG_INVALID); + g_return_val_if_fail(str, MU_FLAG_INVALID); for (cur = str, newflags = oldflags; *cur; ++cur) { - MuFlags f; if (*cur == '+' || *cur == '-') { - f = mu_flag_from_char (cur[1]); + f = mu_flag_from_char(cur[1]); if (f == 0) goto error; if (*cur == '+') - newflags |= f; + newflags |= f; else - newflags &= ~f; + newflags &= ~f; ++cur; continue; } @@ -236,7 +215,6 @@ Mu::mu_flags_from_str_delta (const char *str, MuFlags oldflags, return newflags; error: - g_warning ("invalid flag string"); + g_warning("invalid flag string"); return MU_FLAG_INVALID; - } diff --git a/lib/mu-flags.hh b/lib/mu-flags.hh index af8727f8..6e2046aa 100644 --- a/lib/mu-flags.hh +++ b/lib/mu-flags.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_FLAGS_HH__ #define MU_FLAGS_HH__ @@ -27,53 +26,51 @@ namespace Mu { enum MuFlags { - MU_FLAG_NONE = 0, + MU_FLAG_NONE = 0, /* next 6 are seen in the file-info part of maildir message * file names, ie., in a name like "1234345346:2,", * consists of zero or more of the following * characters (in ascii order) */ - MU_FLAG_DRAFT = 1 << 0, - MU_FLAG_FLAGGED = 1 << 1, - MU_FLAG_PASSED = 1 << 2, - MU_FLAG_REPLIED = 1 << 3, - MU_FLAG_SEEN = 1 << 4, - MU_FLAG_TRASHED = 1 << 5, + MU_FLAG_DRAFT = 1 << 0, + MU_FLAG_FLAGGED = 1 << 1, + MU_FLAG_PASSED = 1 << 2, + MU_FLAG_REPLIED = 1 << 3, + MU_FLAG_SEEN = 1 << 4, + MU_FLAG_TRASHED = 1 << 5, /* decides on cur/ or new/ in the maildir */ - MU_FLAG_NEW = 1 << 6, + MU_FLAG_NEW = 1 << 6, /* content flags -- not visible in the filename, but used for * searching */ - MU_FLAG_SIGNED = 1 << 7, - MU_FLAG_ENCRYPTED = 1 << 8, - MU_FLAG_HAS_ATTACH = 1 << 9, + MU_FLAG_SIGNED = 1 << 7, + MU_FLAG_ENCRYPTED = 1 << 8, + MU_FLAG_HAS_ATTACH = 1 << 9, /* pseudo-flag, only for queries, so we can search for * flag:unread, which is equivalent to 'flag:new OR NOT * flag:seen' */ - MU_FLAG_UNREAD = 1 << 10, + MU_FLAG_UNREAD = 1 << 10, /* other content flags */ - MU_FLAG_LIST = 1 << 11 + MU_FLAG_LIST = 1 << 11 }; MU_ENABLE_BITOPS(MuFlags); - #define MU_FLAG_INVALID ((MuFlags)-1) enum MuFlagType { - MU_FLAG_TYPE_MAILFILE = 1 << 0, - MU_FLAG_TYPE_MAILDIR = 1 << 1, - MU_FLAG_TYPE_CONTENT = 1 << 2, - MU_FLAG_TYPE_PSEUDO = 1 << 3 + MU_FLAG_TYPE_MAILFILE = 1 << 0, + MU_FLAG_TYPE_MAILDIR = 1 << 1, + MU_FLAG_TYPE_CONTENT = 1 << 2, + MU_FLAG_TYPE_PSEUDO = 1 << 3 }; MU_ENABLE_BITOPS(MuFlagType); -#define MU_FLAG_TYPE_ANY ((MuFlagType)-1) +#define MU_FLAG_TYPE_ANY ((MuFlagType)-1) #define MU_FLAG_TYPE_INVALID ((MuFlagType)-1) - /** * Get the type of flag (mailfile, maildir, pseudo or content) * @@ -81,8 +78,7 @@ MU_ENABLE_BITOPS(MuFlagType); * * @return the flag type or MU_FLAG_TYPE_INVALID in case of error */ -MuFlagType mu_flag_type (MuFlags flag) G_GNUC_CONST; - +MuFlagType mu_flag_type(MuFlags flag) G_GNUC_CONST; /** * Get the flag character @@ -91,8 +87,7 @@ MuFlagType mu_flag_type (MuFlags flag) G_GNUC_CONST; * * @return the character, or 0 if it's not a valid flag */ -char mu_flag_char (MuFlags flag) G_GNUC_CONST; - +char mu_flag_char(MuFlags flag) G_GNUC_CONST; /** * Get the flag name @@ -101,8 +96,7 @@ char mu_flag_char (MuFlags flag) G_GNUC_CONST; * * @return the name (don't free) as string or NULL in case of error */ -const char* mu_flag_name (MuFlags flag) G_GNUC_CONST; - +const char* mu_flag_name(MuFlags flag) G_GNUC_CONST; /** * Get the string representation of an OR'ed set of flags @@ -113,8 +107,7 @@ const char* mu_flag_name (MuFlags flag) G_GNUC_CONST; * @return The string representation (static, don't free), or NULL in * case of error */ -const char* mu_flags_to_str_s (MuFlags flags, MuFlagType types); - +const char* mu_flags_to_str_s(MuFlags flags, MuFlagType types); /** * Get the (OR'ed) flags corresponding to a string representation @@ -126,11 +119,7 @@ const char* mu_flags_to_str_s (MuFlags flags, MuFlagType types); * * @return the (OR'ed) flags */ -MuFlags mu_flags_from_str (const char *str, MuFlagType types, - gboolean ignore_invalid); - - - +MuFlags mu_flags_from_str(const char* str, MuFlagType types, gboolean ignore_invalid); /** * Get the MuFlag char for some flag name @@ -139,8 +128,7 @@ MuFlags mu_flags_from_str (const char *str, MuFlagType types, * * @return a flag character, or 0 */ -MuFlags mu_flag_char_from_name (const char *str); - +MuFlags mu_flag_char_from_name(const char* str); /** * return the concatenation of all non-standard file flags in str @@ -151,8 +139,7 @@ MuFlags mu_flag_char_from_name (const char *str); * @return concatenation of all non-standard flags, as a string; free * with g_free when done. If there are no such flags, return NULL. */ -char* mu_flags_custom_from_str (const char *str) G_GNUC_WARN_UNUSED_RESULT; - +char* mu_flags_custom_from_str(const char* str) G_GNUC_WARN_UNUSED_RESULT; /** * Update #oldflags with the flags in #str, where #str consists of the @@ -167,11 +154,9 @@ char* mu_flags_custom_from_str (const char *str) G_GNUC_WARN_UNUSED_RESULT; * * @return */ -MuFlags mu_flags_from_str_delta (const char *str, MuFlags oldflags, - MuFlagType types); +MuFlags mu_flags_from_str_delta(const char* str, MuFlags oldflags, MuFlagType types); - -typedef void (*MuFlagsForeachFunc) (MuFlags flag, gpointer user_data); +typedef void (*MuFlagsForeachFunc)(MuFlags flag, gpointer user_data); /** * call a function for each available flag @@ -179,9 +164,8 @@ typedef void (*MuFlagsForeachFunc) (MuFlags flag, gpointer user_data); * @param func a function to call * @param user_data a user pointer to pass to the function */ -void mu_flags_foreach (MuFlagsForeachFunc func, gpointer user_data); +void mu_flags_foreach(MuFlagsForeachFunc func, gpointer user_data); } // namespace Mu - #endif /*__MU_FLAGS_H__*/ diff --git a/lib/mu-maildir.cc b/lib/mu-maildir.cc index 47fb0e87..22198d8c 100644 --- a/lib/mu-maildir.cc +++ b/lib/mu-maildir.cc @@ -35,8 +35,8 @@ using namespace Mu; -#define MU_MAILDIR_NOINDEX_FILE ".noindex" -#define MU_MAILDIR_NOUPDATE_FILE ".noupdate" +#define MU_MAILDIR_NOINDEX_FILE ".noindex" +#define MU_MAILDIR_NOUPDATE_FILE ".noupdate" /* On Linux (and some BSD), we have entry->d_type, but some file * systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN. @@ -45,7 +45,7 @@ using namespace Mu; * and return it in the d_type parameter */ static unsigned char -get_dtype (struct dirent* dentry, const char *path, gboolean use_lstat) +get_dtype(struct dirent* dentry, const char* path, gboolean use_lstat) { #ifdef HAVE_STRUCT_DIRENT_D_TYPE @@ -58,73 +58,74 @@ get_dtype (struct dirent* dentry, const char *path, gboolean use_lstat) slowpath: #endif /*HAVE_STRUCT_DIRENT_D_TYPE*/ - return mu_util_get_dtype (path, use_lstat); + return mu_util_get_dtype(path, use_lstat); } static gboolean -create_maildir (const char *path, mode_t mode, GError **err) +create_maildir(const char* path, mode_t mode, GError** err) { - int i; + int i; const char* subdirs[] = {"new", "cur", "tmp"}; for (i = 0; i != G_N_ELEMENTS(subdirs); ++i) { - - const char *fullpath; - int rv; + const char* fullpath; + int rv; /* static buffer */ - fullpath = mu_str_fullpath_s (path, subdirs[i]); + fullpath = mu_str_fullpath_s(path, subdirs[i]); /* if subdir already exists, don't try to re-create * it */ - if (mu_util_check_dir (fullpath, TRUE, TRUE)) + if (mu_util_check_dir(fullpath, TRUE, TRUE)) continue; - rv = g_mkdir_with_parents (fullpath, (int)mode); + rv = g_mkdir_with_parents(fullpath, (int)mode); /* note, g_mkdir_with_parents won't detect an error if * there's already such a dir, but with the wrong * permissions; so we need to check */ if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE)) - return mu_util_g_set_error - (err,MU_ERROR_FILE_CANNOT_MKDIR, - "creating dir failed for %s: %s", - fullpath, g_strerror (errno)); + return mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_MKDIR, + "creating dir failed for %s: %s", + fullpath, + g_strerror(errno)); } return TRUE; } static gboolean -create_noindex (const char *path, GError **err) +create_noindex(const char* path, GError** err) { /* create a noindex file if requested */ - int fd; - const char *noindexpath; + int fd; + const char* noindexpath; /* static buffer */ - noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE); + noindexpath = mu_str_fullpath_s(path, MU_MAILDIR_NOINDEX_FILE); - fd = creat (noindexpath, 0644); + fd = creat(noindexpath, 0644); /* note, if the 'close' failed, creation may still have * succeeded...*/ - if (fd < 0 || close (fd) != 0) - return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_CREATE, - "error in create_noindex: %s", - g_strerror (errno)); + if (fd < 0 || close(fd) != 0) + return mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_CREATE, + "error in create_noindex: %s", + g_strerror(errno)); return TRUE; } gboolean -Mu::mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError **err) +Mu::mu_maildir_mkdir(const char* path, mode_t mode, gboolean noindex, GError** err) { - g_return_val_if_fail (path, FALSE); + g_return_val_if_fail(path, FALSE); - if (!create_maildir (path, mode, err)) + if (!create_maildir(path, mode, err)) return FALSE; - if (noindex && !create_noindex (path, err)) + if (noindex && !create_noindex(path, err)) return FALSE; return TRUE; @@ -133,93 +134,93 @@ Mu::mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError ** /* determine whether the source message is in 'new' or in 'cur'; * we ignore messages in 'tmp' for obvious reasons */ static gboolean -check_subdir (const char *src, gboolean *in_cur, GError **err) +check_subdir(const char* src, gboolean* in_cur, GError** err) { gboolean rv; - char *srcpath; + char* srcpath; - srcpath = g_path_get_dirname (src); + srcpath = g_path_get_dirname(src); *in_cur = FALSE; - rv = TRUE; + rv = TRUE; - if (g_str_has_suffix (srcpath, "cur")) + if (g_str_has_suffix(srcpath, "cur")) *in_cur = TRUE; - else if (!g_str_has_suffix (srcpath, "new")) - rv = mu_util_g_set_error (err, - MU_ERROR_FILE_INVALID_SOURCE, - "invalid source message '%s'", - src); - g_free (srcpath); + else if (!g_str_has_suffix(srcpath, "new")) + rv = mu_util_g_set_error(err, + MU_ERROR_FILE_INVALID_SOURCE, + "invalid source message '%s'", + src); + g_free(srcpath); return rv; } static char* -get_target_fullpath (const char* src, const char *targetpath, GError **err) +get_target_fullpath(const char* src, const char* targetpath, GError** err) { - char *targetfullpath, *srcfile; + char * targetfullpath, *srcfile; gboolean in_cur; - if (!check_subdir (src, &in_cur, err)) + if (!check_subdir(src, &in_cur, err)) return NULL; - srcfile = g_path_get_basename (src); + srcfile = g_path_get_basename(src); /* create targetpath; note: make the filename *cough* unique * by including a hash of the srcname in the targetname. This * helps if there are copies of a message (which all have the * same basename) */ - targetfullpath = g_strdup_printf ("%s%c%s%c%u_%s", - targetpath, - G_DIR_SEPARATOR, - in_cur ? "cur" : "new", - G_DIR_SEPARATOR, - g_str_hash(src), - srcfile); - g_free (srcfile); + targetfullpath = g_strdup_printf("%s%c%s%c%u_%s", + targetpath, + G_DIR_SEPARATOR, + in_cur ? "cur" : "new", + G_DIR_SEPARATOR, + g_str_hash(src), + srcfile); + g_free(srcfile); return targetfullpath; } - gboolean -Mu::mu_maildir_link (const char* src, const char *targetpath, GError **err) +Mu::mu_maildir_link(const char* src, const char* targetpath, GError** err) { - char *targetfullpath; - int rv; + char* targetfullpath; + int rv; - g_return_val_if_fail (src, FALSE); - g_return_val_if_fail (targetpath, FALSE); + g_return_val_if_fail(src, FALSE); + g_return_val_if_fail(targetpath, FALSE); - targetfullpath = get_target_fullpath (src, targetpath, err); + targetfullpath = get_target_fullpath(src, targetpath, err); if (!targetfullpath) return FALSE; - rv = symlink (src, targetfullpath); + rv = symlink(src, targetfullpath); if (rv != 0) - mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_LINK, - "error creating link %s => %s: %s", - targetfullpath, src, g_strerror (errno)); - g_free (targetfullpath); + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_LINK, + "error creating link %s => %s: %s", + targetfullpath, + src, + g_strerror(errno)); + g_free(targetfullpath); - return rv == 0 ? TRUE: FALSE; + return rv == 0 ? TRUE : FALSE; } - - /* * determine if path is a maildir leaf-dir; ie. if it's 'cur' or 'new' * (we're skipping 'tmp' for obvious reasons) */ gboolean -Mu::mu_maildir_is_leaf_dir (const char *path) +Mu::mu_maildir_is_leaf_dir(const char* path) { size_t len; /* path is the full path; it cannot possibly be shorter * than 4 for a maildir (/cur or /new) */ - len = path ? strlen (path) : 0; + len = path ? strlen(path) : 0; if (G_UNLIKELY(len < 4)) return FALSE; @@ -227,97 +228,93 @@ Mu::mu_maildir_is_leaf_dir (const char *path) * integer and compare that -- need to think about alignment, * endianness */ - if (path[len - 4] == G_DIR_SEPARATOR && - path[len - 3] == 'c' && - path[len - 2] == 'u' && + if (path[len - 4] == G_DIR_SEPARATOR && path[len - 3] == 'c' && path[len - 2] == 'u' && path[len - 1] == 'r') return TRUE; - if (path[len - 4] == G_DIR_SEPARATOR && - path[len - 3] == 'n' && - path[len - 2] == 'e' && + if (path[len - 4] == G_DIR_SEPARATOR && path[len - 3] == 'n' && path[len - 2] == 'e' && path[len - 1] == 'w') return TRUE; return FALSE; } - static gboolean -clear_links (const char *path, DIR *dir) +clear_links(const char* path, DIR* dir) { - gboolean rv; - struct dirent *dentry; + gboolean rv; + struct dirent* dentry; rv = TRUE; errno = 0; - while ((dentry = readdir (dir))) { - - guint8 d_type; - char *fullpath; + while ((dentry = readdir(dir))) { + guint8 d_type; + char* fullpath; if (dentry->d_name[0] == '.') continue; /* ignore .,.. other dotdirs */ - fullpath = g_build_path ("/", path, dentry->d_name, NULL); - d_type = get_dtype (dentry, fullpath, TRUE/*lstat*/); + fullpath = g_build_path("/", path, dentry->d_name, NULL); + d_type = get_dtype(dentry, fullpath, TRUE /*lstat*/); if (d_type == DT_LNK) { - if (unlink (fullpath) != 0 ) { - g_warning ("error unlinking %s: %s", - fullpath, g_strerror(errno)); + if (unlink(fullpath) != 0) { + g_warning("error unlinking %s: %s", fullpath, g_strerror(errno)); rv = FALSE; } } else if (d_type == DT_DIR) { - DIR *subdir; - subdir = opendir (fullpath); + DIR* subdir; + subdir = opendir(fullpath); if (!subdir) { - g_warning ("failed to open dir %s: %s", - fullpath, g_strerror(errno)); + g_warning("failed to open dir %s: %s", fullpath, g_strerror(errno)); rv = FALSE; goto next; } - if (!clear_links (fullpath, subdir)) + if (!clear_links(fullpath, subdir)) rv = FALSE; - closedir (subdir); + closedir(subdir); } next: - g_free (fullpath); + g_free(fullpath); } return rv; } gboolean -Mu::mu_maildir_clear_links (const char *path, GError **err) +Mu::mu_maildir_clear_links(const char* path, GError** err) { - DIR *dir; - gboolean rv; + DIR* dir; + gboolean rv; - g_return_val_if_fail (path, FALSE); + g_return_val_if_fail(path, FALSE); - dir = opendir (path); + dir = opendir(path); if (!dir) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN, - "failed to open %s: %s", path, g_strerror(errno)); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE_CANNOT_OPEN, + "failed to open %s: %s", + path, + g_strerror(errno)); return FALSE; } - rv = clear_links (path, dir); + rv = clear_links(path, dir); - closedir (dir); + closedir(dir); return rv; } MuFlags -Mu::mu_maildir_get_flags_from_path (const char *path) +Mu::mu_maildir_get_flags_from_path(const char* path) { - g_return_val_if_fail (path, MU_FLAG_INVALID); + g_return_val_if_fail(path, MU_FLAG_INVALID); /* try to find the info part */ /* note that we can use either the ':', ';', or '!' as separator; @@ -330,21 +327,20 @@ Mu::mu_maildir_get_flags_from_path (const char *path) */ /* we check the dir -- */ - if (strstr (path, G_DIR_SEPARATOR_S "new" G_DIR_SEPARATOR_S)) { - - char *dir, *dir2; + if (strstr(path, G_DIR_SEPARATOR_S "new" G_DIR_SEPARATOR_S)) { + char * dir, *dir2; MuFlags flags; - dir = g_path_get_dirname (path); - dir2 = g_path_get_basename (dir); + dir = g_path_get_dirname(path); + dir2 = g_path_get_basename(dir); flags = MU_FLAG_NONE; - if (g_strcmp0 (dir2, "new") == 0) + if (g_strcmp0(dir2, "new") == 0) flags = MU_FLAG_NEW; - g_free (dir); - g_free (dir2); + g_free(dir); + g_free(dir2); /* NOTE: new/ message should not have :2,-stuff, as * per http://cr.yp.to/proto/maildir.html. If they, do @@ -356,21 +352,19 @@ Mu::mu_maildir_get_flags_from_path (const char *path) /* get the file flags */ { - const char *info; + const char* info; - info = strrchr (path, '2'); + info = strrchr(path, '2'); if (!info || info == path || - (info[-1] != ':' && info[-1] != '!' && info[-1] != ';') || - (info[1] != ',')) + (info[-1] != ':' && info[-1] != '!' && info[-1] != ';') || (info[1] != ',')) return MU_FLAG_NONE; else - return mu_flags_from_str - (&info[2], MU_FLAG_TYPE_MAILFILE, - TRUE /*ignore invalid */); + return mu_flags_from_str(&info[2], + MU_FLAG_TYPE_MAILFILE, + TRUE /*ignore invalid */); } } - /* * take an existing message path, and return a new path, based on * whether it should be in 'new' or 'cur'; ie. @@ -386,38 +380,45 @@ Mu::mu_maildir_get_flags_from_path (const char *path) * */ static char* -get_new_path (const char *mdir, const char *mfile, MuFlags flags, - const char* custom_flags, char flags_sep) +get_new_path(const char* mdir, + const char* mfile, + MuFlags flags, + const char* custom_flags, + char flags_sep) { if (flags & MU_FLAG_NEW) - return g_strdup_printf ("%s%cnew%c%s", - mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, - mfile); + return g_strdup_printf("%s%cnew%c%s", + mdir, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + mfile); else { - const char *flagstr; - flagstr = mu_flags_to_str_s (flags, MU_FLAG_TYPE_MAILFILE); + const char* flagstr; + flagstr = mu_flags_to_str_s(flags, MU_FLAG_TYPE_MAILFILE); - return g_strdup_printf ("%s%ccur%c%s%c2,%s%s", - mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, - mfile, flags_sep, flagstr, - custom_flags ? custom_flags : ""); + return g_strdup_printf("%s%ccur%c%s%c2,%s%s", + mdir, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + mfile, + flags_sep, + flagstr, + custom_flags ? custom_flags : ""); } } - char* -Mu::mu_maildir_get_maildir_from_path (const char* path) +Mu::mu_maildir_get_maildir_from_path(const char* path) { - char *mdir; + char* mdir; /* determine the maildir */ - mdir = g_path_get_dirname (path); - if (!g_str_has_suffix (mdir, "cur") && + mdir = g_path_get_dirname(path); + if (!g_str_has_suffix(mdir, "cur") && - !g_str_has_suffix (mdir, "new")) { - g_warning ("%s: not a valid maildir path: %s", - __func__, path); - g_free (mdir); + !g_str_has_suffix(mdir, "new")) { + g_warning("%s: not a valid maildir path: %s", __func__, path); + g_free(mdir); return NULL; } @@ -427,22 +428,21 @@ Mu::mu_maildir_get_maildir_from_path (const char* path) return mdir; } - static char* -get_new_basename (void) +get_new_basename(void) { - return g_strdup_printf ("%u.%08x%08x.%s", - (guint)time(NULL), - g_random_int(), - (gint32)g_get_monotonic_time (), - g_get_host_name ()); + return g_strdup_printf("%u.%08x%08x.%s", + (guint)time(NULL), + g_random_int(), + (gint32)g_get_monotonic_time(), + g_get_host_name()); } static char* -find_path_separator(const char *path) +find_path_separator(const char* path) { - const char *cur; - for (cur = &path[strlen(path)-1]; cur > path; --cur) { + const char* cur; + for (cur = &path[strlen(path) - 1]; cur > path; --cur) { if ((*cur == ':' || *cur == '!' || *cur == ';') && (cur[1] == '2' && cur[2] == ',')) { return (char*)cur; @@ -452,60 +452,61 @@ find_path_separator(const char *path) } char* -Mu::mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, - MuFlags newflags, gboolean new_name) +Mu::mu_maildir_get_new_path(const char* oldpath, + const char* new_mdir, + MuFlags newflags, + gboolean new_name) { char *mfile, *mdir, *custom_flags, *cur, *newpath, flags_sep = ':'; - g_return_val_if_fail (oldpath, NULL); + g_return_val_if_fail(oldpath, NULL); mfile = newpath = custom_flags = NULL; /* determine the maildir */ - mdir = mu_maildir_get_maildir_from_path (oldpath); + mdir = mu_maildir_get_maildir_from_path(oldpath); if (!mdir) return NULL; - /* determine the name of the location of the flag separator */ + /* determine the name of the location of the flag separator */ if (new_name) { - mfile = get_new_basename (); - cur = find_path_separator (oldpath); + mfile = get_new_basename(); + cur = find_path_separator(oldpath); if (cur) { /* preserve the existing flags separator * in the new file name */ flags_sep = *cur; } } else { - mfile = g_path_get_basename (oldpath); - cur = find_path_separator (mfile); + mfile = g_path_get_basename(oldpath); + cur = find_path_separator(mfile); if (cur) { /* get the custom flags (if any) */ - custom_flags = mu_flags_custom_from_str (cur + 3); + custom_flags = mu_flags_custom_from_str(cur + 3); /* preserve the existing flags separator * in the new file name */ flags_sep = *cur; - cur[0] = '\0'; /* strip the flags */ + cur[0] = '\0'; /* strip the flags */ } } - newpath = get_new_path (new_mdir ? new_mdir : mdir, - mfile, newflags, custom_flags, flags_sep); - g_free (mfile); - g_free (mdir); - g_free (custom_flags); + newpath = + get_new_path(new_mdir ? new_mdir : mdir, mfile, newflags, custom_flags, flags_sep); + g_free(mfile); + g_free(mdir); + g_free(custom_flags); return newpath; } - static gint64 -get_file_size (const char* path) +get_file_size(const char* path) { - int rv; - struct stat statbuf; + int rv; + struct stat statbuf; - rv = stat (path, &statbuf); + rv = stat(path, &statbuf); if (rv != 0) { /* g_warning ("error: %s", g_strerror (errno)); */ return -1; @@ -514,62 +515,62 @@ get_file_size (const char* path) return (gint64)statbuf.st_size; } - static gboolean -msg_move_check_pre (const char *src, const char *dst, GError **err) +msg_move_check_pre(const char* src, const char* dst, GError** err) { gint size1, size2; if (!g_path_is_absolute(src)) - return mu_util_g_set_error - (err, MU_ERROR_FILE, - "source is not an absolute path: '%s'", src); + return mu_util_g_set_error(err, + MU_ERROR_FILE, + "source is not an absolute path: '%s'", + src); if (!g_path_is_absolute(dst)) - return mu_util_g_set_error - (err, MU_ERROR_FILE, - "target is not an absolute path: '%s'", dst); + return mu_util_g_set_error(err, + MU_ERROR_FILE, + "target is not an absolute path: '%s'", + dst); - if (access (src, R_OK) != 0) - return mu_util_g_set_error (err, MU_ERROR_FILE, - "cannot read %s", src); + if (access(src, R_OK) != 0) + return mu_util_g_set_error(err, MU_ERROR_FILE, "cannot read %s", src); - if (access (dst, F_OK) != 0) + if (access(dst, F_OK) != 0) return TRUE; /* target exist; we simply overwrite it, unless target has a different * size. ignore the exceedingly rare case where have duplicate message * file names with different content yet the same length. (md5 etc. is a * bit slow) */ - size1 = get_file_size (src); - size2 = get_file_size (dst); + size1 = get_file_size(src); + size2 = get_file_size(dst); if (size1 != size2) - return mu_util_g_set_error (err, MU_ERROR_FILE, - "%s already exists", dst); + return mu_util_g_set_error(err, MU_ERROR_FILE, "%s already exists", dst); return TRUE; } static gboolean -msg_move_check_post (const char *src, const char *dst, GError **err) +msg_move_check_post(const char* src, const char* dst, GError** err) { /* double check -- is the target really there? */ - if (access (dst, F_OK) != 0) - return mu_util_g_set_error - (err, MU_ERROR_FILE, "can't find target (%s->%s)", src, dst); + if (access(dst, F_OK) != 0) + return mu_util_g_set_error(err, + MU_ERROR_FILE, + "can't find target (%s->%s)", + src, + dst); - if (access (src, F_OK) == 0) { + if (access(src, F_OK) == 0) { + if (g_strcmp0(src, dst) == 0) { + g_warning("moved %s to itself", src); + return TRUE; + } - if (g_strcmp0(src, dst) == 0) { - g_warning ("moved %s to itself", src); - return TRUE; - } - - /* this could happen if some other tool (for mail syncing) is - * interfering */ - g_debug ("the source is still there (%s->%s)", - src, dst); - } + /* this could happen if some other tool (for mail syncing) is + * interfering */ + g_debug("the source is still there (%s->%s)", src, dst); + } return TRUE; } @@ -577,65 +578,65 @@ msg_move_check_post (const char *src, const char *dst, GError **err) /* use GIO to move files; this is slower than rename() so only use * this when needed: when moving across filesystems */ static gboolean -msg_move_g_file (const char* src, const char *dst, GError **err) +msg_move_g_file(const char* src, const char* dst, GError** err) { - GFile *srcfile, *dstfile; - gboolean res; + GFile * srcfile, *dstfile; + gboolean res; - srcfile = g_file_new_for_path (src); - dstfile = g_file_new_for_path (dst); + srcfile = g_file_new_for_path(src); + dstfile = g_file_new_for_path(dst); - res = g_file_move (srcfile, dstfile, G_FILE_COPY_NONE, - NULL, NULL, NULL, err); + res = g_file_move(srcfile, dstfile, G_FILE_COPY_NONE, NULL, NULL, NULL, err); - g_clear_object (&srcfile); - g_clear_object (&dstfile); + g_clear_object(&srcfile); + g_clear_object(&dstfile); return res; } static gboolean -msg_move (const char* src, const char *dst, GError **err) +msg_move(const char* src, const char* dst, GError** err) { - if (!msg_move_check_pre (src, dst, err)) + if (!msg_move_check_pre(src, dst, err)) return FALSE; - if (rename (src, dst) == 0) /* seems it worked. */ - return msg_move_check_post (src, dst, err); + if (rename(src, dst) == 0) /* seems it worked. */ + return msg_move_check_post(src, dst, err); if (errno != EXDEV) /* some unrecoverable error occurred */ - return mu_util_g_set_error - (err, MU_ERROR_FILE, "error moving %s -> %s", src, dst); + return mu_util_g_set_error(err, MU_ERROR_FILE, "error moving %s -> %s", src, dst); /* he EXDEV case -- source and target live on different filesystems */ - return msg_move_g_file (src, dst, err); + return msg_move_g_file(src, dst, err); } char* -Mu::mu_maildir_move_message (const char* oldpath, const char* targetmdir, - MuFlags newflags, gboolean ignore_dups, - gboolean new_name, GError **err) +Mu::mu_maildir_move_message(const char* oldpath, + const char* targetmdir, + MuFlags newflags, + gboolean ignore_dups, + gboolean new_name, + GError** err) { - char *newfullpath; - gboolean rv; - gboolean src_is_target; + char* newfullpath; + gboolean rv; + gboolean src_is_target; - g_return_val_if_fail (oldpath, FALSE); + g_return_val_if_fail(oldpath, FALSE); /* first try *without* changing the name (as per new_name), since * src_is_target shouldn't use a changed name */ - newfullpath = mu_maildir_get_new_path (oldpath, targetmdir, - newflags, FALSE); + newfullpath = mu_maildir_get_new_path(oldpath, targetmdir, newflags, FALSE); if (!newfullpath) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "failed to determine targetpath"); + mu_util_g_set_error(err, MU_ERROR_FILE, "failed to determine targetpath"); return NULL; } - src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0); + src_is_target = (g_strcmp0(oldpath, newfullpath) == 0); if (!ignore_dups && src_is_target) { - mu_util_g_set_error (err, MU_ERROR_FILE_TARGET_EQUALS_SOURCE, - "target equals source"); + mu_util_g_set_error(err, + MU_ERROR_FILE_TARGET_EQUALS_SOURCE, + "target equals source"); return NULL; } @@ -643,22 +644,23 @@ Mu::mu_maildir_move_message (const char* oldpath, const char* targetmdir, * new name in the new_name case */ if (!src_is_target && new_name) { g_free(newfullpath); - newfullpath = mu_maildir_get_new_path (oldpath, targetmdir, - newflags, new_name); + newfullpath = mu_maildir_get_new_path(oldpath, targetmdir, newflags, new_name); if (!newfullpath) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "failed to determine targetpath"); + mu_util_g_set_error(err, MU_ERROR_FILE, "failed to determine targetpath"); return NULL; } } if (!src_is_target) { - g_debug ("moving %s (%s, %x, %d) --> %s", - oldpath, targetmdir, newflags, new_name, - newfullpath); - rv = msg_move (oldpath, newfullpath, err); + g_debug("moving %s (%s, %x, %d) --> %s", + oldpath, + targetmdir, + newflags, + new_name, + newfullpath); + rv = msg_move(oldpath, newfullpath, err); if (!rv) { - g_free (newfullpath); + g_free(newfullpath); return NULL; } } diff --git a/lib/mu-maildir.hh b/lib/mu-maildir.hh index 98f9958a..085e7f9f 100644 --- a/lib/mu-maildir.hh +++ b/lib/mu-maildir.hh @@ -22,7 +22,7 @@ #include #include -#include /* for mode_t */ +#include /* for mode_t */ #include #include @@ -45,9 +45,7 @@ namespace Mu { * * @return TRUE if creation succeeded (or already existed), FALSE otherwise */ -gboolean mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, - GError **err); - +gboolean mu_maildir_mkdir(const char* path, mode_t mode, gboolean noindex, GError** err); /** * create a symbolic link to a mail message @@ -61,8 +59,7 @@ gboolean mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, * * @return */ -gboolean mu_maildir_link (const char* src, const char *targetpath, - GError **err); +gboolean mu_maildir_link(const char* src, const char* targetpath, GError** err); /** * recursively delete all the symbolic links in a directory tree @@ -73,15 +70,14 @@ gboolean mu_maildir_link (const char* src, const char *targetpath, * * @return TRUE if it worked, FALSE in case of error */ -gboolean mu_maildir_clear_links (const char* dir, GError **err); +gboolean mu_maildir_clear_links(const char* dir, GError** err); /** * whether the directory path ends in '/cur/' or '/new/' * * @param path some path */ -gboolean mu_maildir_is_leaf_dir (const char *path); - +gboolean mu_maildir_is_leaf_dir(const char* path); /** * get the Maildir flags from the full path of a mailfile. The flags @@ -95,7 +91,7 @@ gboolean mu_maildir_is_leaf_dir (const char *path); * * @return the flags, or MU_MSG_FILE_FLAG_UNKNOWN in case of error */ -MuFlags mu_maildir_get_flags_from_path (const char* pathname); +MuFlags mu_maildir_get_flags_from_path(const char* pathname); /** * get the new pathname for a message, based on the old path and the @@ -120,9 +116,10 @@ MuFlags mu_maildir_get_flags_from_path (const char* pathname); * @return a new path name; use g_free when done with. NULL in case of * error. */ -char* mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, - MuFlags new_flags, gboolean new_name) - G_GNUC_WARN_UNUSED_RESULT; +char* mu_maildir_get_new_path(const char* oldpath, + const char* new_mdir, + MuFlags new_flags, + gboolean new_name) G_GNUC_WARN_UNUSED_RESULT; /** * get the maildir for a certain message path, ie, the path *before* @@ -132,9 +129,7 @@ char* mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, * * @return the maildir (free with g_free), or NULL in case of error */ -char* mu_maildir_get_maildir_from_path (const char* path) - G_GNUC_WARN_UNUSED_RESULT; - +char* mu_maildir_get_maildir_from_path(const char* path) G_GNUC_WARN_UNUSED_RESULT; /** * move a message file to another maildir; the function returns the full path to @@ -158,10 +153,12 @@ char* mu_maildir_get_maildir_from_path (const char* path) * @return return the full path name of the target file (g_free) if * the move succeeded, NULL otherwise */ -char* mu_maildir_move_message (const char* oldpath, const char* targetmdir, - MuFlags newflags, gboolean ignore_dups, - gboolean new_name, GError **err) - G_GNUC_WARN_UNUSED_RESULT; +char* mu_maildir_move_message(const char* oldpath, + const char* targetmdir, + MuFlags newflags, + gboolean ignore_dups, + gboolean new_name, + GError** err) G_GNUC_WARN_UNUSED_RESULT; } // namespace Mu diff --git a/lib/mu-msg-crypto.cc b/lib/mu-msg-crypto.cc index 909292d0..5e30a22f 100644 --- a/lib/mu-msg-crypto.cc +++ b/lib/mu-msg-crypto.cc @@ -32,348 +32,307 @@ using namespace Mu; static const char* -get_pubkey_algo_name (GMimePubKeyAlgo algo) +get_pubkey_algo_name(GMimePubKeyAlgo algo) { #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (algo) { - case GMIME_PUBKEY_ALGO_DEFAULT: - return "default"; - case GMIME_PUBKEY_ALGO_RSA: - return "RSA"; - case GMIME_PUBKEY_ALGO_RSA_E: - return "RSA (encryption only)"; - case GMIME_PUBKEY_ALGO_RSA_S: - return "RSA (signing only)"; - case GMIME_PUBKEY_ALGO_ELG_E: - return "ElGamal (encryption only)"; - case GMIME_PUBKEY_ALGO_DSA: - return "DSA"; - case GMIME_PUBKEY_ALGO_ELG: - return "ElGamal"; - default: - return "unknown pubkey algorithm"; + case GMIME_PUBKEY_ALGO_DEFAULT: return "default"; + case GMIME_PUBKEY_ALGO_RSA: return "RSA"; + case GMIME_PUBKEY_ALGO_RSA_E: return "RSA (encryption only)"; + case GMIME_PUBKEY_ALGO_RSA_S: return "RSA (signing only)"; + case GMIME_PUBKEY_ALGO_ELG_E: return "ElGamal (encryption only)"; + case GMIME_PUBKEY_ALGO_DSA: return "DSA"; + case GMIME_PUBKEY_ALGO_ELG: return "ElGamal"; + default: return "unknown pubkey algorithm"; } #pragma GCC diagnostic pop - } static const gchar* -get_digestkey_algo_name (GMimeDigestAlgo algo) +get_digestkey_algo_name(GMimeDigestAlgo algo) { #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (algo) { - case GMIME_DIGEST_ALGO_DEFAULT: - return "default"; - case GMIME_DIGEST_ALGO_MD5: - return "MD5"; - case GMIME_DIGEST_ALGO_SHA1: - return "SHA-1"; - case GMIME_DIGEST_ALGO_RIPEMD160: - return "RIPEMD160"; - case GMIME_DIGEST_ALGO_MD2: - return "MD2"; - case GMIME_DIGEST_ALGO_TIGER192: - return "TIGER-192"; - case GMIME_DIGEST_ALGO_HAVAL5160: - return "HAVAL-5-160"; - case GMIME_DIGEST_ALGO_SHA256: - return "SHA-256"; - case GMIME_DIGEST_ALGO_SHA384: - return "SHA-384"; - case GMIME_DIGEST_ALGO_SHA512: - return "SHA-512"; - case GMIME_DIGEST_ALGO_SHA224: - return "SHA-224"; - case GMIME_DIGEST_ALGO_MD4: - return "MD4"; - default: - return "unknown digest algorithm"; + case GMIME_DIGEST_ALGO_DEFAULT: return "default"; + case GMIME_DIGEST_ALGO_MD5: return "MD5"; + case GMIME_DIGEST_ALGO_SHA1: return "SHA-1"; + case GMIME_DIGEST_ALGO_RIPEMD160: return "RIPEMD160"; + case GMIME_DIGEST_ALGO_MD2: return "MD2"; + case GMIME_DIGEST_ALGO_TIGER192: return "TIGER-192"; + case GMIME_DIGEST_ALGO_HAVAL5160: return "HAVAL-5-160"; + case GMIME_DIGEST_ALGO_SHA256: return "SHA-256"; + case GMIME_DIGEST_ALGO_SHA384: return "SHA-384"; + case GMIME_DIGEST_ALGO_SHA512: return "SHA-512"; + case GMIME_DIGEST_ALGO_SHA224: return "SHA-224"; + case GMIME_DIGEST_ALGO_MD4: return "MD4"; + default: return "unknown digest algorithm"; } #pragma GCC diagnostic pop } - /* get data from the 'certificate' */ static char* -get_cert_data (GMimeCertificate *cert) +get_cert_data(GMimeCertificate* cert) { - const char /**email,*/ *name, *digest_algo, *pubkey_algo, - *keyid, *trust; + const char /**email,*/ *name, *digest_algo, *pubkey_algo, *keyid, *trust; /* email = g_mime_certificate_get_email (cert); */ - name = g_mime_certificate_get_name (cert); - keyid = g_mime_certificate_get_key_id (cert); + name = g_mime_certificate_get_name(cert); + keyid = g_mime_certificate_get_key_id(cert); - digest_algo = get_digestkey_algo_name - (g_mime_certificate_get_digest_algo (cert)); - pubkey_algo = get_pubkey_algo_name - (g_mime_certificate_get_pubkey_algo (cert)); + digest_algo = get_digestkey_algo_name(g_mime_certificate_get_digest_algo(cert)); + pubkey_algo = get_pubkey_algo_name(g_mime_certificate_get_pubkey_algo(cert)); - switch (g_mime_certificate_get_trust (cert)) { - case GMIME_TRUST_UNKNOWN: trust = "unknown"; break; + switch (g_mime_certificate_get_trust(cert)) { + case GMIME_TRUST_UNKNOWN: trust = "unknown"; break; case GMIME_TRUST_UNDEFINED: trust = "undefined"; break; - case GMIME_TRUST_NEVER: trust = "never"; break; - case GMIME_TRUST_MARGINAL: trust = "marginal"; break; - case GMIME_TRUST_FULL: trust = "full"; break; - case GMIME_TRUST_ULTIMATE: trust = "ultimate"; break; - default: - g_return_val_if_reached (NULL); + case GMIME_TRUST_NEVER: trust = "never"; break; + case GMIME_TRUST_MARGINAL: trust = "marginal"; break; + case GMIME_TRUST_FULL: trust = "full"; break; + case GMIME_TRUST_ULTIMATE: trust = "ultimate"; break; + default: g_return_val_if_reached(NULL); } - return g_strdup_printf ( - "signer:%s, key:%s (%s,%s), trust:%s", - name ? name : "?", - /* email ? email : "?", */ - keyid, pubkey_algo, digest_algo, - trust); + return g_strdup_printf("signer:%s, key:%s (%s,%s), trust:%s", + name ? name : "?", + /* email ? email : "?", */ + keyid, + pubkey_algo, + digest_algo, + trust); } - static char* -get_signature_status (GMimeSignatureStatus status) +get_signature_status(GMimeSignatureStatus status) { - size_t n; - GString *descr; + size_t n; + GString* descr; - struct { - GMimeSignatureStatus status; - const char *name; - } status_info[] = { - { GMIME_SIGNATURE_STATUS_VALID, "valid" }, - { GMIME_SIGNATURE_STATUS_GREEN, "green" }, - { GMIME_SIGNATURE_STATUS_RED, "red" }, - { GMIME_SIGNATURE_STATUS_KEY_REVOKED, "key revoked" }, - { GMIME_SIGNATURE_STATUS_KEY_EXPIRED, "key expired" }, - { GMIME_SIGNATURE_STATUS_SIG_EXPIRED, "signature expired" }, - { GMIME_SIGNATURE_STATUS_KEY_MISSING, "key missing" }, - { GMIME_SIGNATURE_STATUS_CRL_MISSING, "crl missing" }, - { GMIME_SIGNATURE_STATUS_CRL_TOO_OLD, "crl too old" }, - { GMIME_SIGNATURE_STATUS_BAD_POLICY, "bad policy" }, - { GMIME_SIGNATURE_STATUS_SYS_ERROR, "system error" }, - { GMIME_SIGNATURE_STATUS_TOFU_CONFLICT, "tofu conflict " }, - }; + struct { + GMimeSignatureStatus status; + const char* name; + } status_info[] = { + {GMIME_SIGNATURE_STATUS_VALID, "valid"}, + {GMIME_SIGNATURE_STATUS_GREEN, "green"}, + {GMIME_SIGNATURE_STATUS_RED, "red"}, + {GMIME_SIGNATURE_STATUS_KEY_REVOKED, "key revoked"}, + {GMIME_SIGNATURE_STATUS_KEY_EXPIRED, "key expired"}, + {GMIME_SIGNATURE_STATUS_SIG_EXPIRED, "signature expired"}, + {GMIME_SIGNATURE_STATUS_KEY_MISSING, "key missing"}, + {GMIME_SIGNATURE_STATUS_CRL_MISSING, "crl missing"}, + {GMIME_SIGNATURE_STATUS_CRL_TOO_OLD, "crl too old"}, + {GMIME_SIGNATURE_STATUS_BAD_POLICY, "bad policy"}, + {GMIME_SIGNATURE_STATUS_SYS_ERROR, "system error"}, + {GMIME_SIGNATURE_STATUS_TOFU_CONFLICT, "tofu conflict "}, + }; - descr = g_string_new(""); - for (n = 0; n != G_N_ELEMENTS(status_info); ++n) { + descr = g_string_new(""); + for (n = 0; n != G_N_ELEMENTS(status_info); ++n) { + if (!(status & status_info[n].status)) + continue; - if (!(status & status_info[n].status)) - continue; + g_string_append_printf(descr, + "%s%s", + descr->len > 0 ? ", " : "", + status_info[n].name); + } - g_string_append_printf (descr, "%s%s", - descr->len > 0 ? ", " : "", - status_info[n].name); - } - - return g_string_free (descr, FALSE); + return g_string_free(descr, FALSE); } - /* get a human-readable report about the signature */ static char* -get_verdict_report (GMimeSignature *msig) +get_verdict_report(GMimeSignature* msig) { - time_t t; - const char *created, *expires; - gchar *certdata, *report, *status; - GMimeSignatureStatus sigstat; + time_t t; + const char * created, *expires; + gchar * certdata, *report, *status; + GMimeSignatureStatus sigstat; - sigstat = g_mime_signature_get_status (msig); - status = get_signature_status(sigstat); + sigstat = g_mime_signature_get_status(msig); + status = get_signature_status(sigstat); - t = g_mime_signature_get_created (msig); - created = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t); + t = g_mime_signature_get_created(msig); + created = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s("%x", t); - t = g_mime_signature_get_expires (msig); - expires = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s ("%x", t); + t = g_mime_signature_get_expires(msig); + expires = (t == 0 || t == (time_t)-1) ? "?" : mu_date_str_s("%x", t); - certdata = get_cert_data (g_mime_signature_get_certificate (msig)); - report = g_strdup_printf ("%s; created:%s, expires:%s, %s", - status, created, expires, - certdata ? certdata : "?"); - g_free (certdata); - g_free (status); + certdata = get_cert_data(g_mime_signature_get_certificate(msig)); + report = g_strdup_printf("%s; created:%s, expires:%s, %s", + status, + created, + expires, + certdata ? certdata : "?"); + g_free(certdata); + g_free(status); return report; } - static char* -get_signers (GHashTable *signerhash) +get_signers(GHashTable* signerhash) { - GString *gstr; - GHashTableIter iter; - char *name; + GString* gstr; + GHashTableIter iter; + char* name; if (!signerhash || g_hash_table_size(signerhash) == 0) return NULL; - gstr = g_string_new (NULL); - g_hash_table_iter_init (&iter, signerhash); + gstr = g_string_new(NULL); + g_hash_table_iter_init(&iter, signerhash); - while (g_hash_table_iter_next (&iter, reinterpret_cast(&name), NULL)) { + while (g_hash_table_iter_next(&iter, reinterpret_cast(&name), NULL)) { if (gstr->len != 0) - g_string_append_c (gstr, ','); - gstr = g_string_append (gstr, name); + g_string_append_c(gstr, ','); + gstr = g_string_append(gstr, name); } - return g_string_free (gstr, FALSE); + return g_string_free(gstr, FALSE); } - static MuMsgPartSigStatusReport* -get_status_report (GMimeSignatureList *sigs) +get_status_report(GMimeSignatureList* sigs) { - int i; - MuMsgPartSigStatus status; - MuMsgPartSigStatusReport *status_report; - char *report; - GHashTable *signerhash; + int i; + MuMsgPartSigStatus status; + MuMsgPartSigStatusReport* status_report; + char* report; + GHashTable* signerhash; - status = MU_MSG_PART_SIG_STATUS_GOOD; /* let's start positive! */ - signerhash = g_hash_table_new (g_str_hash, g_str_equal); + status = MU_MSG_PART_SIG_STATUS_GOOD; /* let's start positive! */ + signerhash = g_hash_table_new(g_str_hash, g_str_equal); - for (i = 0, report = NULL; i != g_mime_signature_list_length (sigs); - ++i) { + for (i = 0, report = NULL; i != g_mime_signature_list_length(sigs); ++i) { + GMimeSignature* msig; + GMimeCertificate* cert; + GMimeSignatureStatus sigstat; + gchar* rep; - GMimeSignature *msig; - GMimeCertificate *cert; - GMimeSignatureStatus sigstat; - gchar *rep; - - msig = g_mime_signature_list_get_signature (sigs, i); - sigstat = g_mime_signature_get_status (msig); + msig = g_mime_signature_list_get_signature(sigs, i); + sigstat = g_mime_signature_get_status(msig); /* downgrade our expectations */ if ((sigstat & GMIME_SIGNATURE_STATUS_ERROR_MASK) && status != MU_MSG_PART_SIG_STATUS_ERROR) status = MU_MSG_PART_SIG_STATUS_ERROR; else if ((sigstat & GMIME_SIGNATURE_STATUS_RED) && - status == MU_MSG_PART_SIG_STATUS_GOOD) + status == MU_MSG_PART_SIG_STATUS_GOOD) status = MU_MSG_PART_SIG_STATUS_BAD; - rep = get_verdict_report (msig); - report = g_strdup_printf ("%s%s%d: %s", - report ? report : "", - report ? "; " : "", i + 1, - rep); - g_free (rep); + rep = get_verdict_report(msig); + report = g_strdup_printf("%s%s%d: %s", + report ? report : "", + report ? "; " : "", + i + 1, + rep); + g_free(rep); - cert = g_mime_signature_get_certificate (msig); - if (cert && g_mime_certificate_get_name (cert)) - g_hash_table_add ( - signerhash, - (gpointer)g_mime_certificate_get_name (cert)); + cert = g_mime_signature_get_certificate(msig); + if (cert && g_mime_certificate_get_name(cert)) + g_hash_table_add(signerhash, (gpointer)g_mime_certificate_get_name(cert)); } - status_report = g_slice_new0 (MuMsgPartSigStatusReport); + status_report = g_slice_new0(MuMsgPartSigStatusReport); status_report->verdict = status; status_report->report = report; status_report->signers = get_signers(signerhash); - g_hash_table_unref (signerhash); + g_hash_table_unref(signerhash); return status_report; } void -Mu::mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report) +Mu::mu_msg_part_sig_status_report_destroy(MuMsgPartSigStatusReport* report) { if (!report) return; - g_free ((char*)report->report); - g_free ((char*)report->signers); + g_free((char*)report->report); + g_free((char*)report->signers); - g_slice_free (MuMsgPartSigStatusReport, report); + g_slice_free(MuMsgPartSigStatusReport, report); } - static inline void -tag_with_sig_status(GObject *part, - MuMsgPartSigStatusReport *report) +tag_with_sig_status(GObject* part, MuMsgPartSigStatusReport* report) { - g_object_set_data_full - (part, SIG_STATUS_REPORT, report, - (GDestroyNotify)mu_msg_part_sig_status_report_destroy); + g_object_set_data_full(part, + SIG_STATUS_REPORT, + report, + (GDestroyNotify)mu_msg_part_sig_status_report_destroy); } - void -Mu::mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts, - GError **err) +Mu::mu_msg_crypto_verify_part(GMimeMultipartSigned* sig, MuMsgOptions opts, GError** err) { /* the signature status */ - MuMsgPartSigStatusReport *report; - GMimeSignatureList *sigs; + MuMsgPartSigStatusReport* report; + GMimeSignatureList* sigs; - g_return_if_fail (GMIME_IS_MULTIPART_SIGNED(sig)); + g_return_if_fail(GMIME_IS_MULTIPART_SIGNED(sig)); - sigs = g_mime_multipart_signed_verify (sig, GMIME_VERIFY_NONE, err); + sigs = g_mime_multipart_signed_verify(sig, GMIME_VERIFY_NONE, err); if (!sigs) { if (err && !*err) - mu_util_g_set_error (err, MU_ERROR_CRYPTO, - "verification failed"); + mu_util_g_set_error(err, MU_ERROR_CRYPTO, "verification failed"); return; } - report = get_status_report (sigs); - g_clear_object (&sigs); + report = get_status_report(sigs); + g_clear_object(&sigs); /* tag this part with the signature status check */ tag_with_sig_status(G_OBJECT(sig), report); } - static inline void -check_decrypt_result(GMimeMultipartEncrypted *part, GMimeDecryptResult *res, - GError **err) +check_decrypt_result(GMimeMultipartEncrypted* part, GMimeDecryptResult* res, GError** err) { - GMimeSignatureList *sigs; - MuMsgPartSigStatusReport *report; + GMimeSignatureList* sigs; + MuMsgPartSigStatusReport* report; if (res) { /* Check if the decrypted part had any embed signatures */ sigs = res->signatures; if (sigs) { - report = get_status_report (sigs); - g_mime_signature_list_clear (sigs); + report = get_status_report(sigs); + g_mime_signature_list_clear(sigs); /* tag this part with the signature status check */ tag_with_sig_status(G_OBJECT(part), report); - } - else { + } else { if (err && !*err) - mu_util_g_set_error (err, MU_ERROR_CRYPTO, - "verification failed"); + mu_util_g_set_error(err, MU_ERROR_CRYPTO, "verification failed"); } - g_object_unref (res); + g_object_unref(res); } - } - GMimeObject* /* this is declared in mu-msg-priv.h */ -Mu::mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts, - MuMsgPartPasswordFunc func, gpointer user_data, - GError **err) +Mu::mu_msg_crypto_decrypt_part(GMimeMultipartEncrypted* enc, + MuMsgOptions opts, + MuMsgPartPasswordFunc func, + gpointer user_data, + GError** err) { - GMimeObject *dec; - GMimeDecryptResult *res; + GMimeObject* dec; + GMimeDecryptResult* res; - g_return_val_if_fail (GMIME_IS_MULTIPART_ENCRYPTED(enc), NULL); + g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(enc), NULL); res = NULL; - dec = g_mime_multipart_encrypted_decrypt (enc, GMIME_DECRYPT_NONE, NULL, - &res, err); + dec = g_mime_multipart_encrypted_decrypt(enc, GMIME_DECRYPT_NONE, NULL, &res, err); check_decrypt_result(enc, res, err); if (!dec) { if (err && !*err) - mu_util_g_set_error (err, MU_ERROR_CRYPTO, - "decryption failed"); + mu_util_g_set_error(err, MU_ERROR_CRYPTO, "decryption failed"); return NULL; } diff --git a/lib/mu-msg-doc.cc b/lib/mu-msg-doc.cc index 0df4f91d..a3ad22b8 100644 --- a/lib/mu-msg-doc.cc +++ b/lib/mu-msg-doc.cc @@ -34,42 +34,37 @@ using namespace Mu; struct Mu::MuMsgDoc { - MuMsgDoc (Xapian::Document *doc): _doc (doc) { } - ~MuMsgDoc () { delete _doc; } + MuMsgDoc(Xapian::Document* doc) : _doc(doc) {} + ~MuMsgDoc() { delete _doc; } const Xapian::Document doc() const { return *_doc; } -private: - Xapian::Document *_doc; + + private: + Xapian::Document* _doc; }; - MuMsgDoc* -Mu::mu_msg_doc_new (XapianDocument *doc, GError **err) +Mu::mu_msg_doc_new(XapianDocument* doc, GError** err) { - g_return_val_if_fail (doc, NULL); + g_return_val_if_fail(doc, NULL); + MuMsgDoc* mdoc = + xapian_try([&] { return new MuMsgDoc((Xapian::Document*)doc); }, (MuMsgDoc*)nullptr); - try { - return new MuMsgDoc ((Xapian::Document*)doc); - - } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN, NULL); - - return FALSE; + if (!mdoc) + mu_util_g_set_error(err, MU_ERROR_INTERNAL, "failed to create message doc"); + return mdoc; } void -Mu::mu_msg_doc_destroy (MuMsgDoc *self) +Mu::mu_msg_doc_destroy(MuMsgDoc* self) { - try { - delete self; - - } MU_XAPIAN_CATCH_BLOCK; + xapian_try([&] { delete self; }); } - gchar* -Mu::mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid) +Mu::mu_msg_doc_get_str_field(MuMsgDoc* self, MuMsgFieldId mfid) { - 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(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); @@ -78,48 +73,47 @@ Mu::mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid) // have to convert to numbers first, esp. when it's a date // time_t) - try { - const std::string s (self->doc().get_value(mfid)); - return s.empty() ? NULL : g_strdup (s.c_str()); - - } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); + return xapian_try( + [&] { + const std::string s(self->doc().get_value(mfid)); + 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, MuMsgFieldId mfid) { - 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(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); - try { - /* return a comma-separated string as a GSList */ - const std::string s (self->doc().get_value(mfid)); - return s.empty() ? NULL : mu_str_to_list(s.c_str(),',',TRUE); - - } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); + return xapian_try( + [&] { + /* return a comma-separated string as a GSList */ + const std::string s(self->doc().get_value(mfid)); + 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, MuMsgFieldId mfid) { - 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(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); - try { - const std::string s (self->doc().get_value(mfid)); - if (s.empty()) - return 0; - else if (mfid == MU_MSG_FIELD_ID_DATE || - mfid == MU_MSG_FIELD_ID_SIZE) - return strtol (s.c_str(), NULL, 10); - else { - return static_cast - (Xapian::sortable_unserialise(s)); - } - - } MU_XAPIAN_CATCH_BLOCK_RETURN(-1); + return xapian_try( + [&] { + const std::string s(self->doc().get_value(mfid)); + if (s.empty()) + return (gint64)0; + else if (mfid == MU_MSG_FIELD_ID_DATE || mfid == MU_MSG_FIELD_ID_SIZE) + return static_cast(strtol(s.c_str(), NULL, 10)); + else { + return static_cast(Xapian::sortable_unserialise(s)); + } + }, + (gint64)-1); } diff --git a/lib/mu-msg-doc.hh b/lib/mu-msg-doc.hh index f9258809..b5999b87 100644 --- a/lib/mu-msg-doc.hh +++ b/lib/mu-msg-doc.hh @@ -23,7 +23,6 @@ #include #include - namespace Mu { struct MuMsgDoc; @@ -40,8 +39,7 @@ struct MuMsgDoc; * @return a new MuMsgDoc instance (free with mu_msg_doc_destroy), or * NULL in case of error. */ -MuMsgDoc* mu_msg_doc_new (XapianDocument *doc, GError **err) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +MuMsgDoc* mu_msg_doc_new(XapianDocument* doc, GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * destroy a MuMsgDoc instance -- free all the resources. Note, after @@ -50,8 +48,7 @@ MuMsgDoc* mu_msg_doc_new (XapianDocument *doc, GError **err) * * @param self a MuMsgDoc instance */ -void mu_msg_doc_destroy (MuMsgDoc *self); - +void mu_msg_doc_destroy(MuMsgDoc* self); /** * get a string parameter from the msgdoc @@ -62,8 +59,7 @@ void mu_msg_doc_destroy (MuMsgDoc *self); * @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, MuMsgFieldId mfid) G_GNUC_WARN_UNUSED_RESULT; /** * get a string-list parameter from the msgdoc @@ -74,9 +70,7 @@ gchar* mu_msg_doc_get_str_field (MuMsgDoc *self, MuMsgFieldId mfid) * @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, MuMsgFieldId mfid) G_GNUC_WARN_UNUSED_RESULT; /** * @@ -88,7 +82,7 @@ GSList* mu_msg_doc_get_str_list_field (MuMsgDoc *self, MuMsgFieldId mfid) * @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) */ -gint64 mu_msg_doc_get_num_field (MuMsgDoc *self, MuMsgFieldId mfid); +gint64 mu_msg_doc_get_num_field(MuMsgDoc* self, MuMsgFieldId mfid); } // namespace Mu diff --git a/lib/mu-msg-file.cc b/lib/mu-msg-file.cc index efa0bba1..62db5581 100644 --- a/lib/mu-msg-file.cc +++ b/lib/mu-msg-file.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2012-2020 Dirk-Jan C. Binnema +** Copyright (C) 2012-2021 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 @@ -37,80 +37,82 @@ using namespace Mu; -static gboolean init_file_metadata (MuMsgFile *self, const char* path, - const char *mdir, GError **err); -static gboolean init_mime_msg (MuMsgFile *msg, const char *path, GError **err); +static gboolean +init_file_metadata(MuMsgFile* self, const char* path, const char* mdir, GError** err); +static gboolean init_mime_msg(MuMsgFile* msg, const char* path, GError** err); MuMsgFile* -Mu::mu_msg_file_new (const char* filepath, const char *mdir, GError **err) +Mu::mu_msg_file_new(const char* filepath, const char* mdir, GError** err) { - MuMsgFile *self; + MuMsgFile* self; - g_return_val_if_fail (filepath, NULL); + g_return_val_if_fail(filepath, NULL); - self = g_new0(MuMsgFile, 1); + self = g_new0(MuMsgFile, 1); - if (!init_file_metadata (self, filepath, mdir, err)) { - mu_msg_file_destroy (self); - return NULL; - } + if (!init_file_metadata(self, filepath, mdir, err)) { + mu_msg_file_destroy(self); + return NULL; + } - if (!init_mime_msg (self, filepath, err)) { - mu_msg_file_destroy (self); - return NULL; - } + if (!init_mime_msg(self, filepath, err)) { + mu_msg_file_destroy(self); + return NULL; + } - return self; + return self; } void -Mu::mu_msg_file_destroy (MuMsgFile *self) +Mu::mu_msg_file_destroy(MuMsgFile* self) { if (!self) return; - g_clear_object(&self->_mime_msg); + g_clear_object(&self->_mime_msg); g_free(self->_path); g_free(self->_maildir); + g_free(self->_sha1); - g_free (self); + g_free(self); } static gboolean -init_file_metadata (MuMsgFile *self, const char* path, const gchar* mdir, - GError **err) +init_file_metadata(MuMsgFile* self, const char* path, const gchar* mdir, GError** err) { struct stat statbuf; - if (!g_path_is_absolute (path)) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "path '%s' is not absolute", path); + if (!g_path_is_absolute(path)) { + mu_util_g_set_error(err, MU_ERROR_FILE, "path '%s' is not absolute", path); return FALSE; } - if (access (path, R_OK) != 0) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "cannot read file %s: %s", - path, g_strerror(errno)); + if (access(path, R_OK) != 0) { + mu_util_g_set_error(err, + 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)); + if (stat(path, &statbuf) < 0) { + mu_util_g_set_error(err, + MU_ERROR_FILE, + "cannot stat %s: %s", + path, + g_strerror(errno)); return FALSE; } if (!S_ISREG(statbuf.st_mode)) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "not a regular file: %s", path); + mu_util_g_set_error(err, MU_ERROR_FILE, "not a regular file: %s", path); return FALSE; } self->_timestamp = statbuf.st_mtime; - self->_size = (size_t)statbuf.st_size; + self->_size = (size_t)statbuf.st_size; self->_path = mu_canonicalize_filename(path, NULL); self->_maildir = g_strdup(mdir ? mdir : ""); @@ -118,86 +120,100 @@ init_file_metadata (MuMsgFile *self, const char* path, const gchar* mdir, } static char* -calculate_sha1 (FILE *file) +calculate_sha1(FILE* file) { - std::array buf{}; - char *sha1{}; - GChecksum *checksum{g_checksum_new(G_CHECKSUM_SHA256)}; + std::array buf{}; + char* sha1{}; + GChecksum* checksum{g_checksum_new(G_CHECKSUM_SHA256)}; - while (true) { - const auto n = ::fread(buf.data(), 1, buf.size(), file); - if (n == 0) - break; - g_checksum_update (checksum, buf.data(), n); - } + while (true) { + const auto n = ::fread(buf.data(), 1, buf.size(), file); + if (n == 0) + break; + g_checksum_update(checksum, buf.data(), n); + } - if (::ferror(file)) - g_warning ("error reading file"); - else - sha1 = g_strdup(g_checksum_get_string(checksum)); + if (::ferror(file)) + g_warning("error reading file"); + else + sha1 = g_strdup(g_checksum_get_string(checksum)); - g_checksum_free(checksum); + g_checksum_free(checksum); - return sha1; + return sha1; } static GMimeStream* -get_mime_stream (MuMsgFile *self, const char *path, GError **err) +get_mime_stream(MuMsgFile* self, const char* path, GError** err) { - FILE *file; - GMimeStream *stream; + FILE* file; + GMimeStream* stream; - file = fopen (path, "r"); + file = fopen(path, "r"); if (!file) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, - "cannot open %s: %s", - path, g_strerror (errno)); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "cannot open %s: %s", + path, + g_strerror(errno)); return NULL; } - stream = g_mime_stream_file_new (file); + 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); - fclose (file); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "cannot create mime stream for %s", + path); + fclose(file); return NULL; } - self->_sha1 = calculate_sha1(file); - if (!self->_sha1) { - ::fclose(file); - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, - "failed to get sha-1 for %s", path); - return NULL; - } + self->_sha1 = calculate_sha1(file); + if (!self->_sha1) { + ::fclose(file); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "failed to get sha-1 for %s", + path); + return NULL; + } return stream; } static gboolean -init_mime_msg (MuMsgFile *self, const char* path, GError **err) +init_mime_msg(MuMsgFile* self, const char* path, GError** err) { - GMimeStream *stream; - GMimeParser *parser; + GMimeStream* stream; + GMimeParser* parser; - stream = get_mime_stream (self, path, err); + stream = get_mime_stream(self, path, err); if (!stream) return FALSE; - parser = g_mime_parser_new_with_stream (stream); - g_object_unref (stream); + parser = g_mime_parser_new_with_stream(stream); + g_object_unref(stream); if (!parser) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "cannot create mime parser for %s", path); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "cannot create mime parser for %s", + path); return FALSE; } - self->_mime_msg = g_mime_parser_construct_message (parser, NULL); - g_object_unref (parser); + self->_mime_msg = g_mime_parser_construct_message(parser, NULL); + g_object_unref(parser); if (!self->_mime_msg) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "message seems invalid, ignoring (%s)", path); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "message seems invalid, ignoring (%s)", + path); return FALSE; } @@ -205,28 +221,28 @@ init_mime_msg (MuMsgFile *self, const char* path, GError **err) } static char* -get_recipient (MuMsgFile *self, GMimeAddressType atype) +get_recipient(MuMsgFile* self, GMimeAddressType atype) { - char *recip; - InternetAddressList *recips; + char* recip; + InternetAddressList* recips; - recips = g_mime_message_get_addresses (self->_mime_msg, atype); + recips = g_mime_message_get_addresses(self->_mime_msg, atype); /* FALSE --> don't encode */ - recip = (char*)internet_address_list_to_string (recips, NULL, FALSE); + recip = (char*)internet_address_list_to_string(recips, NULL, FALSE); - if (recip && !g_utf8_validate (recip, -1, NULL)) { - g_debug ("invalid recipient in %s\n", self->_path); - mu_str_asciify_in_place (recip); /* ugly... */ + if (recip && !g_utf8_validate(recip, -1, NULL)) { + g_debug("invalid recipient in %s\n", self->_path); + mu_str_asciify_in_place(recip); /* ugly... */ } if (mu_str_is_empty(recip)) { - g_free (recip); + g_free(recip); return NULL; } if (recip) - mu_str_remove_ctrl_in_place (recip); + mu_str_remove_ctrl_in_place(recip); return recip; } @@ -236,12 +252,11 @@ get_recipient (MuMsgFile *self, GMimeAddressType atype) * headers in the mail */ static gchar* -get_fake_mailing_list_maybe (MuMsgFile *self) +get_fake_mailing_list_maybe(MuMsgFile* self) { const char* hdr; - hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), - "X-Feed2Imap-Version"); + hdr = g_mime_object_get_header(GMIME_OBJECT(self->_mime_msg), "X-Feed2Imap-Version"); if (!hdr) return NULL; @@ -249,97 +264,92 @@ get_fake_mailing_list_maybe (MuMsgFile *self) * from the msgid */ { const char *msgid, *e; - msgid = g_mime_message_get_message_id (self->_mime_msg); - if (msgid && (e = strchr (msgid, '-'))) - return g_strndup (msgid, e - msgid); + msgid = g_mime_message_get_message_id(self->_mime_msg); + if (msgid && (e = strchr(msgid, '-'))) + return g_strndup(msgid, e - msgid); } return NULL; } static gchar* -get_mailing_list (MuMsgFile *self) +get_mailing_list(MuMsgFile* self) { - char *dechdr, *res; - const char *hdr, *b, *e; + char * dechdr, *res; + const char *hdr, *b, *e; - hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), - "List-Id"); - if (mu_str_is_empty (hdr)) - return get_fake_mailing_list_maybe (self); + hdr = g_mime_object_get_header(GMIME_OBJECT(self->_mime_msg), "List-Id"); + if (mu_str_is_empty(hdr)) + return get_fake_mailing_list_maybe(self); - dechdr = g_mime_utils_header_decode_phrase (NULL, hdr); + dechdr = g_mime_utils_header_decode_phrase(NULL, hdr); if (!dechdr) return NULL; e = NULL; - b = strchr (dechdr, '<'); + b = strchr(dechdr, '<'); if (b) - e = strchr (b, '>'); + e = strchr(b, '>'); if (b && e) - res = g_strndup (b + 1, e - b - 1); + res = g_strndup(b + 1, e - b - 1); else - res = g_strdup (dechdr); + res = g_strdup(dechdr); - g_free (dechdr); + g_free(dechdr); return res; } static gboolean -looks_like_attachment (GMimeObject *part) +looks_like_attachment(GMimeObject* part) { - - GMimeContentDisposition *disp; - GMimeContentType *ctype; - const char *dispstr; - guint u; + GMimeContentDisposition* disp; + GMimeContentType* ctype; + const char* dispstr; + guint u; const struct { - const char *type; - const char *sub_type; - } att_types[] = { - { "image", "*" }, - { "audio", "*" }, - { "application", "*"}, - { "application", "x-patch"} - }; + const char* type; + const char* sub_type; + } att_types[] = {{"image", "*"}, + {"audio", "*"}, + {"application", "*"}, + {"application", "x-patch"}}; - disp = g_mime_object_get_content_disposition (part); + disp = g_mime_object_get_content_disposition(part); if (!GMIME_IS_CONTENT_DISPOSITION(disp)) return FALSE; - dispstr = g_mime_content_disposition_get_disposition (disp); + dispstr = g_mime_content_disposition_get_disposition(disp); - if (g_ascii_strcasecmp (dispstr, "attachment") == 0) + if (g_ascii_strcasecmp(dispstr, "attachment") == 0) return TRUE; /* we also consider patches, images, audio, and non-pgp-signature * application attachments to be attachments... */ - ctype = g_mime_object_get_content_type (part); + ctype = g_mime_object_get_content_type(part); - if (g_mime_content_type_is_type (ctype, "*", "pgp-signature")) + if (g_mime_content_type_is_type(ctype, "*", "pgp-signature")) return FALSE; /* don't consider as a signature */ - if (g_mime_content_type_is_type (ctype, "text", "*")) { - if (g_mime_content_type_is_type (ctype, "*", "plain") || - g_mime_content_type_is_type (ctype, "*", "html")) + if (g_mime_content_type_is_type(ctype, "text", "*")) { + if (g_mime_content_type_is_type(ctype, "*", "plain") || + g_mime_content_type_is_type(ctype, "*", "html")) return FALSE; else return TRUE; } for (u = 0; u != G_N_ELEMENTS(att_types); ++u) - if (g_mime_content_type_is_type ( - ctype, att_types[u].type, att_types[u].sub_type)) + if (g_mime_content_type_is_type(ctype, att_types[u].type, att_types[u].sub_type)) return TRUE; return FALSE; } static void -msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuFlags *flags) +msg_cflags_cb(GMimeObject* parent, GMimeObject* part, MuFlags* flags) { if (GMIME_IS_MULTIPART_SIGNED(part)) *flags |= MU_FLAG_SIGNED; @@ -358,42 +368,42 @@ msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuFlags *flags) if (*flags & MU_FLAG_HAS_ATTACH) return; - if (looks_like_attachment (part)) + if (looks_like_attachment(part)) *flags |= MU_FLAG_HAS_ATTACH; } static MuFlags -get_content_flags (MuMsgFile *self) +get_content_flags(MuMsgFile* self) { - MuFlags flags; - char *ml; + MuFlags flags; + char* ml; flags = MU_FLAG_NONE; if (GMIME_IS_MESSAGE(self->_mime_msg)) - mu_mime_message_foreach (self->_mime_msg, - FALSE, /* never decrypt for this */ - (GMimeObjectForeachFunc)msg_cflags_cb, - &flags); + mu_mime_message_foreach(self->_mime_msg, + FALSE, /* never decrypt for this */ + (GMimeObjectForeachFunc)msg_cflags_cb, + &flags); - ml = get_mailing_list (self); + ml = get_mailing_list(self); if (ml) { flags |= MU_FLAG_LIST; - g_free (ml); + g_free(ml); } return flags; } static MuFlags -get_flags (MuMsgFile *self) +get_flags(MuMsgFile* self) { MuFlags flags; - g_return_val_if_fail (self, MU_FLAG_INVALID); + g_return_val_if_fail(self, MU_FLAG_INVALID); - flags = mu_maildir_get_flags_from_path (self->_path); - flags |= get_content_flags (self); + flags = mu_maildir_get_flags_from_path(self->_path); + flags |= get_content_flags(self); /* pseudo-flag --> unread means either NEW or NOT SEEN, just * for searching convenience */ @@ -404,36 +414,34 @@ get_flags (MuMsgFile *self) } static size_t -get_size (MuMsgFile *self) +get_size(MuMsgFile* self) { - g_return_val_if_fail (self, 0); + g_return_val_if_fail(self, 0); return self->_size; } static MuMsgPrio -parse_prio_str (const char* priostr) +parse_prio_str(const char* priostr) { int i; struct { - const char* _str; - MuMsgPrio _prio; - } str_prio[] = { - { "high", MU_MSG_PRIO_HIGH }, - { "1", MU_MSG_PRIO_HIGH }, - { "2", MU_MSG_PRIO_HIGH }, + const char* _str; + MuMsgPrio _prio; + } str_prio[] = {{"high", MU_MSG_PRIO_HIGH}, + {"1", MU_MSG_PRIO_HIGH}, + {"2", MU_MSG_PRIO_HIGH}, - { "normal", MU_MSG_PRIO_NORMAL }, - { "3", MU_MSG_PRIO_NORMAL }, + {"normal", MU_MSG_PRIO_NORMAL}, + {"3", MU_MSG_PRIO_NORMAL}, - { "low", MU_MSG_PRIO_LOW }, - { "list", MU_MSG_PRIO_LOW }, - { "bulk", MU_MSG_PRIO_LOW }, - { "4", MU_MSG_PRIO_LOW }, - { "5", MU_MSG_PRIO_LOW } - }; + {"low", MU_MSG_PRIO_LOW}, + {"list", MU_MSG_PRIO_LOW}, + {"bulk", MU_MSG_PRIO_LOW}, + {"4", MU_MSG_PRIO_LOW}, + {"5", MU_MSG_PRIO_LOW}}; for (i = 0; i != G_N_ELEMENTS(str_prio); ++i) - if (g_ascii_strcasecmp (priostr, str_prio[i]._str) == 0) + if (g_ascii_strcasecmp(priostr, str_prio[i]._str) == 0) return str_prio[i]._prio; /* e.g., last-fm uses 'fm-user'... as precedence */ @@ -441,128 +449,127 @@ parse_prio_str (const char* priostr) } static MuMsgPrio -get_prio (MuMsgFile *self) +get_prio(MuMsgFile* self) { - GMimeObject *obj; - const char* priostr; + GMimeObject* obj; + const char* priostr; - g_return_val_if_fail (self, MU_MSG_PRIO_NONE); + g_return_val_if_fail(self, MU_MSG_PRIO_NONE); obj = GMIME_OBJECT(self->_mime_msg); - priostr = g_mime_object_get_header (obj, "Precedence"); + priostr = g_mime_object_get_header(obj, "Precedence"); if (!priostr) - priostr = g_mime_object_get_header (obj, "X-Priority"); + priostr = g_mime_object_get_header(obj, "X-Priority"); if (!priostr) - priostr = g_mime_object_get_header (obj, "Importance"); + priostr = g_mime_object_get_header(obj, "Importance"); - return priostr ? parse_prio_str (priostr) : MU_MSG_PRIO_NORMAL; + return priostr ? parse_prio_str(priostr) : MU_MSG_PRIO_NORMAL; } /* NOTE: buffer will be *freed* or returned unchanged */ static char* -convert_to_utf8 (GMimePart *part, char *buffer) +convert_to_utf8(GMimePart* part, char* buffer) { - GMimeContentType *ctype; - const char* charset; + GMimeContentType* ctype; + const char* charset; - ctype = g_mime_object_get_content_type (GMIME_OBJECT(part)); - g_return_val_if_fail (GMIME_IS_CONTENT_TYPE(ctype), NULL); + ctype = g_mime_object_get_content_type(GMIME_OBJECT(part)); + g_return_val_if_fail(GMIME_IS_CONTENT_TYPE(ctype), NULL); /* of course, the charset specified may be incorrect... */ - charset = g_mime_content_type_get_parameter (ctype, "charset"); + charset = g_mime_content_type_get_parameter(ctype, "charset"); if (charset) { - char *utf8; - if ((utf8 = mu_str_convert_to_utf8 - (buffer, g_mime_charset_iconv_name (charset)))) { - g_free (buffer); + char* utf8; + if ((utf8 = mu_str_convert_to_utf8(buffer, g_mime_charset_iconv_name(charset)))) { + g_free(buffer); buffer = utf8; } - } else if (!g_utf8_validate (buffer, -1, NULL)) { + } else if (!g_utf8_validate(buffer, -1, NULL)) { /* if it's already utf8, nothing to do otherwise: no charset at all, or conversion failed; ugly * hack: replace all non-ascii chars with '.' */ - mu_str_asciify_in_place (buffer); + mu_str_asciify_in_place(buffer); } return buffer; } static gchar* -stream_to_string (GMimeStream *stream, size_t buflen) +stream_to_string(GMimeStream* stream, size_t buflen) { - char *buffer; + char* buffer; ssize_t bytes; buffer = g_new(char, buflen + 1); - g_mime_stream_reset (stream); + g_mime_stream_reset(stream); /* we read everything in one go */ - bytes = g_mime_stream_read (stream, buffer, buflen); + bytes = g_mime_stream_read(stream, buffer, buflen); if (bytes < 0) { - g_warning ("%s: failed to read from stream", __func__); - g_free (buffer); + g_warning("%s: failed to read from stream", __func__); + g_free(buffer); return NULL; } - buffer[bytes]='\0'; + buffer[bytes] = '\0'; return buffer; } gchar* -Mu::mu_msg_mime_part_to_string (GMimePart *part, gboolean *err) +Mu::mu_msg_mime_part_to_string(GMimePart* part, gboolean* err) { - GMimeDataWrapper *wrapper; - GMimeStream *stream; - ssize_t buflen; - char *buffer; + GMimeDataWrapper* wrapper; + GMimeStream* stream; + ssize_t buflen; + char* buffer; buffer = NULL; stream = NULL; - g_return_val_if_fail (err, NULL); + g_return_val_if_fail(err, NULL); *err = TRUE; /* guilty until proven innocent */ - g_return_val_if_fail (GMIME_IS_PART(part), NULL); + g_return_val_if_fail(GMIME_IS_PART(part), NULL); - wrapper = g_mime_part_get_content (part); + wrapper = g_mime_part_get_content(part); if (!wrapper) { /* this happens with invalid mails */ - g_debug ("failed to create data wrapper"); + g_debug("failed to create data wrapper"); goto cleanup; } - stream = g_mime_stream_mem_new (); + stream = g_mime_stream_mem_new(); if (!stream) { - g_warning ("failed to create mem stream"); + g_warning("failed to create mem stream"); goto cleanup; } - buflen = g_mime_data_wrapper_write_to_stream (wrapper, stream); - if (buflen <= 0) {/* empty buffer, not an error */ + buflen = g_mime_data_wrapper_write_to_stream(wrapper, stream); + if (buflen <= 0) { /* empty buffer, not an error */ *err = FALSE; goto cleanup; } - buffer = stream_to_string (stream, (size_t)buflen); + buffer = stream_to_string(stream, (size_t)buflen); /* convert_to_utf8 will free the old 'buffer' if needed */ - buffer = convert_to_utf8 (part, buffer); + buffer = convert_to_utf8(part, buffer); *err = FALSE; cleanup: if (G_IS_OBJECT(stream)) - g_object_unref (stream); + g_object_unref(stream); return buffer; } static gboolean -contains (GSList *lst, const char *str) +contains(GSList* lst, const char* str) { for (; lst; lst = g_slist_next(lst)) - if (g_strcmp0 ((char*)lst->data, str) == 0) + if (g_strcmp0((char*)lst->data, str) == 0) return TRUE; return FALSE; } @@ -571,73 +578,67 @@ contains (GSList *lst, const char *str) * NOTE: this will get the list of references with the oldest parent * at the beginning */ static GSList* -get_references (MuMsgFile *self) +get_references(MuMsgFile* self) { - GSList *msgids; - unsigned u; - const char *headers[] = { "References", "In-reply-to", NULL }; + GSList* msgids; + unsigned u; + const char* headers[] = {"References", "In-reply-to", NULL}; for (msgids = NULL, u = 0; headers[u]; ++u) { + char* str; + GMimeReferences* mime_refs; + int i, refs_len; - char *str; - GMimeReferences *mime_refs; - int i, refs_len; - - str = mu_msg_file_get_header (self, headers[u]); + str = mu_msg_file_get_header(self, headers[u]); if (!str) continue; - mime_refs = g_mime_references_parse (NULL, str); - g_free (str); + mime_refs = g_mime_references_parse(NULL, str); + g_free(str); - refs_len = g_mime_references_length (mime_refs); + refs_len = g_mime_references_length(mime_refs); for (i = 0; i < refs_len; ++i) { const char* msgid; - msgid = g_mime_references_get_message_id (mime_refs, i); + msgid = g_mime_references_get_message_id(mime_refs, i); /* don't include duplicates */ - if (msgid && !contains (msgids, msgid)) + if (msgid && !contains(msgids, msgid)) /* explicitly ensure it's utf8-safe, * as GMime does not ensure that */ - msgids = g_slist_prepend (msgids, - g_strdup((msgid))); + msgids = g_slist_prepend(msgids, g_strdup((msgid))); } - g_mime_references_free (mime_refs); + g_mime_references_free(mime_refs); } /* reverse, because we used g_slist_prepend for performance * reasons */ - return g_slist_reverse (msgids); + return g_slist_reverse(msgids); } /* see: http://does-not-exist.org/mail-archives/mutt-dev/msg08249.html */ static GSList* -get_tags (MuMsgFile *self) +get_tags(MuMsgFile* self) { - GSList *lst; + GSList* lst; unsigned u; struct { - const char *header; - char sepa; - } tagfields[] = { - { "X-Label", ' ' }, - { "X-Keywords", ',' }, - { "Keywords", ' ' } - }; + const char* header; + char sepa; + } tagfields[] = {{"X-Label", ' '}, {"X-Keywords", ','}, {"Keywords", ' '}}; for (lst = NULL, u = 0; u != G_N_ELEMENTS(tagfields); ++u) { - gchar *hdr; - hdr = mu_msg_file_get_header (self, tagfields[u].header); + gchar* hdr; + hdr = mu_msg_file_get_header(self, tagfields[u].header); if (hdr) { - GSList *hlst; - hlst = mu_str_to_list (hdr, tagfields[u].sepa, TRUE); + GSList* hlst; + hlst = mu_str_to_list(hdr, tagfields[u].sepa, TRUE); if (lst) - (g_slist_last (lst))->next = hlst; + (g_slist_last(lst))->next = hlst; else lst = hlst; - g_free (hdr); + g_free(hdr); } } @@ -645,205 +646,190 @@ get_tags (MuMsgFile *self) } static char* -cleanup_maybe (const char *str, gboolean *do_free) +cleanup_maybe(const char* str, gboolean* do_free) { - char *s; + char* s; if (!str) return NULL; if (!g_utf8_validate(str, -1, NULL)) { if (*do_free) - s = mu_str_asciify_in_place ((char*)str); + s = mu_str_asciify_in_place((char*)str); else { *do_free = TRUE; - s = mu_str_asciify_in_place(g_strdup (str)); + s = mu_str_asciify_in_place(g_strdup(str)); } } else s = (char*)str; - mu_str_remove_ctrl_in_place (s); + mu_str_remove_ctrl_in_place(s); return s; } G_GNUC_CONST static GMimeAddressType -address_type (MuMsgFieldId mfid) +address_type(MuMsgFieldId mfid) { 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_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; - default: g_return_val_if_reached ((GMimeAddressType)-1); + default: g_return_val_if_reached((GMimeAddressType)-1); } } static gchar* -get_msgid (MuMsgFile *self, gboolean *do_free) +get_msgid(MuMsgFile* self, gboolean* do_free) { - const char *msgid{g_mime_message_get_message_id (self->_mime_msg)}; - if (msgid && strlen(msgid) < Store::MaxTermLength) { - *do_free = FALSE; - return (char*)msgid; - } - // if there's no valid message-id, synthesize one; - // based on the contents so it stays valid if moved around. - *do_free = TRUE; - return g_strdup_printf ("%s@mu", self->_sha1); + const char* msgid{g_mime_message_get_message_id(self->_mime_msg)}; + if (msgid && strlen(msgid) < Store::MaxTermLength) { + *do_free = FALSE; + return (char*)msgid; + } + // if there's no valid message-id, synthesize one; + // based on the contents so it stays valid if moved around. + *do_free = TRUE; + return g_strdup_printf("%s@mu", self->_sha1); } char* -Mu::mu_msg_file_get_str_field (MuMsgFile *self, MuMsgFieldId mfid, - gboolean *do_free) +Mu::mu_msg_file_get_str_field(MuMsgFile* self, MuMsgFieldId mfid, 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(self, NULL); + g_return_val_if_fail(mu_msg_field_is_string(mfid), 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)); + case MU_MSG_FIELD_ID_TO: *do_free = TRUE; return get_recipient(self, address_type(mfid)); case MU_MSG_FIELD_ID_PATH: return self->_path; - case MU_MSG_FIELD_ID_MAILING_LIST: - *do_free = TRUE; - return (char*)get_mailing_list (self); + case MU_MSG_FIELD_ID_MAILING_LIST: *do_free = TRUE; return (char*)get_mailing_list(self); case MU_MSG_FIELD_ID_SUBJECT: - return (char*)cleanup_maybe - (g_mime_message_get_subject (self->_mime_msg), do_free); + 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 MU_MSG_FIELD_ID_MSGID: return get_msgid(self, do_free); case MU_MSG_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_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__); - return NULL; + g_warning("%s is not retrievable through: %s", mu_msg_field_name(mfid), __func__); + return NULL; - default: g_return_val_if_reached (NULL); + default: g_return_val_if_reached(NULL); } } GSList* -Mu::mu_msg_file_get_str_list_field (MuMsgFile *self, MuMsgFieldId mfid) +Mu::mu_msg_file_get_str_list_field(MuMsgFile* self, MuMsgFieldId mfid) { - 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(self, NULL); + g_return_val_if_fail(mu_msg_field_is_string_list(mfid), NULL); switch (mfid) { - case MU_MSG_FIELD_ID_REFS: return get_references (self); - case MU_MSG_FIELD_ID_TAGS: return get_tags (self); - default: g_return_val_if_reached (NULL); + case MU_MSG_FIELD_ID_REFS: return get_references(self); + case MU_MSG_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 MuMsgFieldId mfid) { - g_return_val_if_fail (self, -1); - g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1); + g_return_val_if_fail(self, -1); + g_return_val_if_fail(mu_msg_field_is_numeric(mfid), -1); switch (mfid) { - case MU_MSG_FIELD_ID_DATE: { - GDateTime *dt; - dt = g_mime_message_get_date (self->_mime_msg); - return dt ? g_date_time_to_unix (dt) : 0; + 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 MU_MSG_FIELD_ID_FLAGS: return (gint64)get_flags(self); - case MU_MSG_FIELD_ID_PRIO: - return (gint64)get_prio(self); + case MU_MSG_FIELD_ID_PRIO: return (gint64)get_prio(self); - case MU_MSG_FIELD_ID_SIZE: - return (gint64)get_size(self); + case MU_MSG_FIELD_ID_SIZE: return (gint64)get_size(self); - default: g_return_val_if_reached (-1); + default: g_return_val_if_reached(-1); } } char* -Mu::mu_msg_file_get_header (MuMsgFile *self, const char *header) +Mu::mu_msg_file_get_header(MuMsgFile* self, const char* header) { - const gchar *hdr; + const gchar* hdr; - g_return_val_if_fail (self, NULL); - g_return_val_if_fail (header, NULL); + g_return_val_if_fail(self, NULL); + g_return_val_if_fail(header, NULL); /* sadly, g_mime_object_get_header may return non-ascii; * so, we need to ensure that */ - hdr = g_mime_object_get_header (GMIME_OBJECT(self->_mime_msg), - header); + hdr = g_mime_object_get_header(GMIME_OBJECT(self->_mime_msg), header); return hdr ? mu_str_utf8ify(hdr) : NULL; } struct _ForeachData { GMimeObjectForeachFunc user_func; - gpointer user_data; - gboolean decrypt; + gpointer user_data; + gboolean decrypt; }; typedef struct _ForeachData ForeachData; static void -foreach_cb (GMimeObject *parent, GMimeObject *part, ForeachData *fdata) +foreach_cb(GMimeObject* parent, GMimeObject* part, ForeachData* fdata) { /* invoke the callback function */ - fdata->user_func (parent, part, fdata->user_data); + fdata->user_func(parent, part, fdata->user_data); /* maybe iterate over decrypted parts */ - 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); + 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); if (!dec) return; - if (GMIME_IS_MULTIPART (dec)) - g_mime_multipart_foreach ( - (GMIME_MULTIPART(dec)), - (GMimeObjectForeachFunc)foreach_cb, - fdata); + if (GMIME_IS_MULTIPART(dec)) + g_mime_multipart_foreach((GMIME_MULTIPART(dec)), + (GMimeObjectForeachFunc)foreach_cb, + fdata); else - foreach_cb (parent, dec, fdata); + foreach_cb(parent, dec, fdata); - g_object_unref (dec); + g_object_unref(dec); } } void -Mu::mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt, - GMimeObjectForeachFunc func, gpointer user_data) +Mu::mu_mime_message_foreach(GMimeMessage* msg, + gboolean decrypt, + GMimeObjectForeachFunc func, + gpointer user_data) { ForeachData fdata; - g_return_if_fail (GMIME_IS_MESSAGE (msg)); - g_return_if_fail (func); + g_return_if_fail(GMIME_IS_MESSAGE(msg)); + g_return_if_fail(func); fdata.user_func = func; fdata.user_data = user_data; fdata.decrypt = decrypt; - g_mime_message_foreach - (msg, - (GMimeObjectForeachFunc)foreach_cb, - &fdata); + g_mime_message_foreach(msg, (GMimeObjectForeachFunc)foreach_cb, &fdata); } diff --git a/lib/mu-msg-file.hh b/lib/mu-msg-file.hh index 0ba9b7db..953ef41f 100644 --- a/lib/mu-msg-file.hh +++ b/lib/mu-msg-file.hh @@ -33,18 +33,16 @@ 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; +MuMsgFile* mu_msg_file_new(const char* path, + const char* mdir, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * destroy a MuMsgFile object * * @param self object to destroy, or NULL */ -void mu_msg_file_destroy (MuMsgFile *self); - - +void mu_msg_file_destroy(MuMsgFile* self); /** * get a specific header @@ -54,8 +52,7 @@ void mu_msg_file_destroy (MuMsgFile *self); * * @return the value of the header or NULL if not found; free with g_free */ -char* mu_msg_file_get_header (MuMsgFile *self, const char *header); - +char* mu_msg_file_get_header(MuMsgFile* self, const char* header); /** * get a string value for this message @@ -70,11 +67,9 @@ 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; - +char* mu_msg_file_get_str_field(MuMsgFile* self, + MuMsgFieldId msfid, + gboolean* do_free) G_GNUC_WARN_UNUSED_RESULT; /** * get a string-list value for this message @@ -84,10 +79,8 @@ 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; - - +GSList* mu_msg_file_get_str_list_field(MuMsgFile* self, + MuMsgFieldId msfid) G_GNUC_WARN_UNUSED_RESULT; /** * get a numeric value for this message -- the return value should be @@ -98,7 +91,7 @@ GSList* mu_msg_file_get_str_list_field (MuMsgFile *self, MuMsgFieldId msfid) * * @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, MuMsgFieldId mfid); } // namespace Mu diff --git a/lib/mu-msg-part.cc b/lib/mu-msg-part.cc index 77724a9f..551bf0f0 100644 --- a/lib/mu-msg-part.cc +++ b/lib/mu-msg-part.cc @@ -31,13 +31,13 @@ using namespace Mu; struct _DoData { - GMimeObject *mime_obj; - unsigned index; + GMimeObject* mime_obj; + unsigned index; }; typedef struct _DoData DoData; static void -do_it_with_index (MuMsg *msg, MuMsgPart *part, DoData *ddata) +do_it_with_index(MuMsg* msg, MuMsgPart* part, DoData* ddata) { if (ddata->mime_obj) return; @@ -46,52 +46,48 @@ do_it_with_index (MuMsg *msg, MuMsgPart *part, DoData *ddata) /* Add a reference to this object, this way if it is * encrypted it will not be garbage collected before * we are done with it. */ - g_object_ref (part->data); + g_object_ref(part->data); ddata->mime_obj = (GMimeObject*)part->data; } } static GMimeObject* -get_mime_object_at_index (MuMsg *msg, MuMsgOptions opts, unsigned index) +get_mime_object_at_index(MuMsg* msg, MuMsgOptions opts, unsigned index) { DoData ddata; - ddata.mime_obj = NULL; - ddata.index = index; + ddata.mime_obj = NULL; + ddata.index = index; /* wipe out some irrelevant options */ opts &= (MuMsgOptions)~MU_MSG_OPTION_VERIFY; opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; - mu_msg_part_foreach (msg, opts, - (MuMsgPartForeachFunc)do_it_with_index, - &ddata); + mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)do_it_with_index, &ddata); return ddata.mime_obj; } - -typedef gboolean (*MuMsgPartMatchFunc) (MuMsgPart *, gpointer); +typedef gboolean (*MuMsgPartMatchFunc)(MuMsgPart*, gpointer); struct _MatchData { MuMsgPartMatchFunc match_func; - gpointer user_data; - int index; + gpointer user_data; + int index; }; typedef struct _MatchData MatchData; static void -check_match (MuMsg *msg, MuMsgPart *part, MatchData *mdata) +check_match(MuMsg* msg, MuMsgPart* part, MatchData* mdata) { if (mdata->index != -1) return; - if (mdata->match_func (part, mdata->user_data)) + if (mdata->match_func(part, mdata->user_data)) mdata->index = part->index; } static int -get_matching_part_index (MuMsg *msg, MuMsgOptions opts, - MuMsgPartMatchFunc func, gpointer user_data) +get_matching_part_index(MuMsg* msg, MuMsgOptions opts, MuMsgPartMatchFunc func, gpointer user_data) { MatchData mdata; @@ -99,181 +95,172 @@ get_matching_part_index (MuMsg *msg, MuMsgOptions opts, mdata.user_data = user_data; mdata.index = -1; - mu_msg_part_foreach (msg, opts, - (MuMsgPartForeachFunc)check_match, - &mdata); + mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)check_match, &mdata); return mdata.index; } - static void -accumulate_text_message (MuMsg *msg, MuMsgPart *part, GString **gstrp) +accumulate_text_message(MuMsg* msg, MuMsgPart* part, GString** gstrp) { - const gchar *str; - char *adrs; - GMimeMessage *mimemsg; - InternetAddressList *addresses; + const gchar* str; + char* adrs; + GMimeMessage* mimemsg; + InternetAddressList* addresses; /* put sender, recipients and subject in the string, so they * can be indexed as well */ - mimemsg = GMIME_MESSAGE (part->data); - addresses = g_mime_message_get_addresses (mimemsg, GMIME_ADDRESS_TYPE_FROM); - adrs = internet_address_list_to_string (addresses, NULL, FALSE); + mimemsg = GMIME_MESSAGE(part->data); + addresses = g_mime_message_get_addresses(mimemsg, GMIME_ADDRESS_TYPE_FROM); + adrs = internet_address_list_to_string(addresses, NULL, FALSE); - g_string_append_printf - (*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); - g_free (adrs); + g_string_append_printf(*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); + g_free(adrs); - str = g_mime_message_get_subject (mimemsg); - g_string_append_printf - (*gstrp, "%s%s", str ? str : "", str ? "\n" : ""); + str = g_mime_message_get_subject(mimemsg); + g_string_append_printf(*gstrp, "%s%s", str ? str : "", str ? "\n" : ""); - addresses = g_mime_message_get_all_recipients (mimemsg); - adrs = internet_address_list_to_string (addresses, NULL, FALSE); - g_object_unref (addresses); + addresses = g_mime_message_get_all_recipients(mimemsg); + adrs = internet_address_list_to_string(addresses, NULL, FALSE); + g_object_unref(addresses); - g_string_append_printf - (*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); - g_free (adrs); + g_string_append_printf(*gstrp, "%s%s", adrs ? adrs : "", adrs ? "\n" : ""); + g_free(adrs); } static void -accumulate_text_part (MuMsg *msg, MuMsgPart *part, GString **gstrp) +accumulate_text_part(MuMsg* msg, MuMsgPart* part, GString** gstrp) { - GMimeContentType *ctype; - gboolean err; - char *txt; + GMimeContentType* ctype; + gboolean err; + char* txt; - ctype = g_mime_object_get_content_type ((GMimeObject*)part->data); - if (!g_mime_content_type_is_type (ctype, "text", "plain")) + ctype = g_mime_object_get_content_type((GMimeObject*)part->data); + if (!g_mime_content_type_is_type(ctype, "text", "plain")) return; /* not plain text */ txt = mu_msg_mime_part_to_string((GMimePart*)part->data, &err); if (txt) - g_string_append (*gstrp, txt); + g_string_append(*gstrp, txt); - g_free (txt); + g_free(txt); } static void -accumulate_text (MuMsg *msg, MuMsgPart *part, GString **gstrp) +accumulate_text(MuMsg* msg, MuMsgPart* part, GString** gstrp) { if (GMIME_IS_MESSAGE(part->data)) - accumulate_text_message (msg, part, gstrp); - else if (GMIME_IS_PART (part->data)) - accumulate_text_part (msg, part, gstrp); + accumulate_text_message(msg, part, gstrp); + else if (GMIME_IS_PART(part->data)) + accumulate_text_part(msg, part, gstrp); } /* declaration, so we can use it earlier */ -static gboolean -handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, - MuMsgOptions opts, unsigned *index, gboolean decrypted, - MuMsgPartForeachFunc func, gpointer user_data); +static gboolean handle_mime_object(MuMsg* msg, + GMimeObject* mobj, + GMimeObject* parent, + MuMsgOptions opts, + unsigned* index, + gboolean decrypted, + MuMsgPartForeachFunc func, + gpointer user_data); static char* -get_text_from_mime_msg (MuMsg *msg, GMimeMessage *mmsg, MuMsgOptions opts) +get_text_from_mime_msg(MuMsg* msg, GMimeMessage* mmsg, MuMsgOptions opts) { - GString *gstr; + GString* gstr; unsigned index; index = 1; - gstr = g_string_sized_new (4096); - handle_mime_object (msg, - mmsg->mime_part, - (GMimeObject *) mmsg, - opts, - &index, - FALSE, - (MuMsgPartForeachFunc)accumulate_text, - &gstr); + gstr = g_string_sized_new(4096); + handle_mime_object(msg, + mmsg->mime_part, + (GMimeObject*)mmsg, + opts, + &index, + FALSE, + (MuMsgPartForeachFunc)accumulate_text, + &gstr); - return g_string_free (gstr, FALSE); + return g_string_free(gstr, FALSE); } - char* -Mu::mu_msg_part_get_text (MuMsg *msg, MuMsgPart *self, MuMsgOptions opts) +Mu::mu_msg_part_get_text(MuMsg* msg, MuMsgPart* self, MuMsgOptions opts) { - GMimeObject *mobj; - GMimeMessage *mime_msg; - gboolean err; + GMimeObject* mobj; + GMimeMessage* mime_msg; + gboolean err; - g_return_val_if_fail (msg, NULL); - g_return_val_if_fail (self && GMIME_IS_OBJECT(self->data), - NULL); + g_return_val_if_fail(msg, NULL); + g_return_val_if_fail(self && GMIME_IS_OBJECT(self->data), NULL); mobj = (GMimeObject*)self->data; err = FALSE; - if (GMIME_IS_PART (mobj)) { + if (GMIME_IS_PART(mobj)) { if (self->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN) - return mu_msg_mime_part_to_string ((GMimePart*)mobj, - &err); + return mu_msg_mime_part_to_string((GMimePart*)mobj, &err); else return NULL; /* non-text MimePart */ } mime_msg = NULL; - if (GMIME_IS_MESSAGE_PART (mobj)) - mime_msg = g_mime_message_part_get_message - ((GMimeMessagePart*)mobj); - else if (GMIME_IS_MESSAGE (mobj)) + if (GMIME_IS_MESSAGE_PART(mobj)) + mime_msg = g_mime_message_part_get_message((GMimeMessagePart*)mobj); + else if (GMIME_IS_MESSAGE(mobj)) mime_msg = (GMimeMessage*)mobj; /* apparently, g_mime_message_part_get_message may still * return NULL */ - if (mime_msg) - return get_text_from_mime_msg (msg, mime_msg, opts); + if (mime_msg) + return get_text_from_mime_msg(msg, mime_msg, opts); return NULL; } - /* note: this will return -1 in case of error or if the size is * unknown */ static ssize_t -get_part_size (GMimePart *part) +get_part_size(GMimePart* part) { - GMimeDataWrapper *wrapper; - GMimeStream *stream; + GMimeDataWrapper* wrapper; + GMimeStream* stream; - wrapper = g_mime_part_get_content (part); + wrapper = g_mime_part_get_content(part); if (!GMIME_IS_DATA_WRAPPER(wrapper)) return -1; - stream = g_mime_data_wrapper_get_stream (wrapper); + stream = g_mime_data_wrapper_get_stream(wrapper); if (!stream) return -1; /* no stream -> size is 0 */ else - return g_mime_stream_length (stream); + return g_mime_stream_length(stream); /* NOTE: stream/wrapper are owned by gmime, no unreffing */ } - static char* -cleanup_filename (char *fname) +cleanup_filename(char* fname) { - GString *gstr; - gchar *cur; + GString* gstr; + gchar* cur; gunichar uc; - gstr = g_string_sized_new (strlen (fname)); + gstr = g_string_sized_new(strlen(fname)); /* replace control characters, slashes, and colons by '-' */ - for (cur = fname; cur && *cur; cur = g_utf8_next_char (cur)) { - uc = g_utf8_get_char (cur); - if (g_unichar_iscntrl (uc) || uc == '/' || uc == ':' || uc == ';') - g_string_append_unichar (gstr, '-'); + for (cur = fname; cur && *cur; cur = g_utf8_next_char(cur)) { + uc = g_utf8_get_char(cur); + if (g_unichar_iscntrl(uc) || uc == '/' || uc == ':' || uc == ';') + g_string_append_unichar(gstr, '-'); else - g_string_append_unichar (gstr, uc); + g_string_append_unichar(gstr, uc); } - g_free (fname); - return g_string_free (gstr, FALSE); + g_free(fname); + return g_string_free(gstr, FALSE); } - /* * when a part doesn't have a filename, it can be useful to 'guess' one based on * its mime-type, which allows other tools to handle them correctly, e.g. from @@ -283,91 +270,84 @@ cleanup_filename (char *fname) * follow. */ static char* -guess_file_name (GMimeObject *mobj, unsigned index) +guess_file_name(GMimeObject* mobj, unsigned index) { - GMimeContentType *ctype; + GMimeContentType* ctype; - ctype = g_mime_object_get_content_type (mobj); + ctype = g_mime_object_get_content_type(mobj); /* special case for calendars; map to '.vcs' */ - if (g_mime_content_type_is_type (ctype, "text", "calendar")) - return g_strdup_printf ("vcal-%u.vcs", index); + if (g_mime_content_type_is_type(ctype, "text", "calendar")) + return g_strdup_printf("vcal-%u.vcs", index); /* fallback */ - return g_strdup_printf ("%u.msgpart", index); + return g_strdup_printf("%u.msgpart", index); } - static char* -mime_part_get_filename (GMimeObject *mobj, unsigned index, - gboolean construct_if_needed) +mime_part_get_filename(GMimeObject* mobj, unsigned index, gboolean construct_if_needed) { - gchar *fname; + gchar* fname; fname = NULL; - if (GMIME_IS_PART (mobj)) { + if (GMIME_IS_PART(mobj)) { /* the easy case: the part has a filename */ - fname = (gchar*)g_mime_part_get_filename (GMIME_PART(mobj)); + fname = (gchar*)g_mime_part_get_filename(GMIME_PART(mobj)); if (fname) /* don't include directory components */ - fname = g_path_get_basename (fname); + fname = g_path_get_basename(fname); } if (!fname && !construct_if_needed) return NULL; if (GMIME_IS_MESSAGE_PART(mobj)) { - GMimeMessage *msg; - const char *subj; - msg = g_mime_message_part_get_message - (GMIME_MESSAGE_PART(mobj)); - subj = g_mime_message_get_subject (msg); - fname = g_strdup_printf ("%s.eml", subj ? subj : "message"); + GMimeMessage* msg; + const char* subj; + msg = g_mime_message_part_get_message(GMIME_MESSAGE_PART(mobj)); + subj = g_mime_message_get_subject(msg); + fname = g_strdup_printf("%s.eml", subj ? subj : "message"); } if (!fname) - fname = guess_file_name (mobj, index); + fname = guess_file_name(mobj, index); /* replace control characters, slashes, and colons */ - fname = cleanup_filename (fname); + fname = cleanup_filename(fname); return fname; } - char* -Mu::mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed) +Mu::mu_msg_part_get_filename(MuMsgPart* mpart, gboolean construct_if_needed) { - g_return_val_if_fail (mpart, NULL); - g_return_val_if_fail (GMIME_IS_OBJECT(mpart->data), NULL); + g_return_val_if_fail(mpart, NULL); + g_return_val_if_fail(GMIME_IS_OBJECT(mpart->data), NULL); - return mime_part_get_filename ((GMimeObject*)mpart->data, - mpart->index, construct_if_needed); + return mime_part_get_filename((GMimeObject*)mpart->data, mpart->index, construct_if_needed); } const gchar* -Mu::mu_msg_part_get_content_id (MuMsgPart *mpart) +Mu::mu_msg_part_get_content_id(MuMsgPart* mpart) { - g_return_val_if_fail (mpart, NULL); - g_return_val_if_fail (GMIME_IS_OBJECT(mpart->data), NULL); + g_return_val_if_fail(mpart, NULL); + g_return_val_if_fail(GMIME_IS_OBJECT(mpart->data), NULL); return g_mime_object_get_content_id((GMimeObject*)mpart->data); } - - static MuMsgPartType -get_disposition (GMimeObject *mobj) +get_disposition(GMimeObject* mobj) { - const char *disp; + const char* disp; - disp = g_mime_object_get_disposition (mobj); + disp = g_mime_object_get_disposition(mobj); if (!disp) return MU_MSG_PART_TYPE_NONE; - if (strcasecmp (disp, GMIME_DISPOSITION_ATTACHMENT) == 0) + if (strcasecmp(disp, GMIME_DISPOSITION_ATTACHMENT) == 0) return MU_MSG_PART_TYPE_ATTACHMENT; - if (strcasecmp (disp, GMIME_DISPOSITION_INLINE) == 0) + if (strcasecmp(disp, GMIME_DISPOSITION_INLINE) == 0) return MU_MSG_PART_TYPE_INLINE; return MU_MSG_PART_TYPE_NONE; @@ -375,58 +355,58 @@ get_disposition (GMimeObject *mobj) /* call 'func' with information about this MIME-part */ static inline void -check_signature (MuMsg *msg, GMimeMultipartSigned *part, MuMsgOptions opts) +check_signature(MuMsg* msg, GMimeMultipartSigned* part, MuMsgOptions opts) { - GError *err; + GError* err; err = NULL; - mu_msg_crypto_verify_part (part, opts, &err); + mu_msg_crypto_verify_part(part, opts, &err); if (err) { - g_warning ("error verifying signature: %s", err->message); - g_clear_error (&err); + g_warning("error verifying signature: %s", err->message); + g_clear_error(&err); } } - /* Note: this is function will be called by GMime when it needs a * password. However, GMime <= 2.6.10 does not handle * getting passwords correctly, so this might fail. see: * password_requester in mu-msg-crypto.c */ static gchar* -get_console_pw (const char* user_id, const char *prompt_ctx, - gboolean reprompt, gpointer user_data) +get_console_pw(const char* user_id, const char* prompt_ctx, gboolean reprompt, gpointer user_data) { char *prompt, *pass; - if (!g_mime_check_version(2,6,11)) - g_printerr ( - "*** the gmime library you are using has version " - "%u.%u.%u (<= 2.6.10)\n" - "*** this version has a bug in its password " - "retrieval routine, and probably won't work.\n", - gmime_major_version, gmime_minor_version, - gmime_micro_version); + if (!g_mime_check_version(2, 6, 11)) + g_printerr("*** the gmime library you are using has version " + "%u.%u.%u (<= 2.6.10)\n" + "*** this version has a bug in its password " + "retrieval routine, and probably won't work.\n", + gmime_major_version, + gmime_minor_version, + gmime_micro_version); if (reprompt) - g_print ("Authentication failed. Please try again\n"); + g_print("Authentication failed. Please try again\n"); - prompt = g_strdup_printf ("Password for %s: ", user_id); + prompt = g_strdup_printf("Password for %s: ", user_id); - pass = mu_util_read_password (prompt); - g_free (prompt); + pass = mu_util_read_password(prompt); + g_free(prompt); return pass; } - static gboolean -handle_encrypted_part (MuMsg *msg, GMimeMultipartEncrypted *part, - MuMsgOptions opts, unsigned *index, - MuMsgPartForeachFunc func, gpointer user_data) +handle_encrypted_part(MuMsg* msg, + GMimeMultipartEncrypted* part, + MuMsgOptions opts, + unsigned* index, + MuMsgPartForeachFunc func, + gpointer user_data) { - GError *err; - gboolean rv; - GMimeObject *dec; + GError* err; + gboolean rv; + GMimeObject* dec; MuMsgPartPasswordFunc pw_func; if (opts & MU_MSG_OPTION_CONSOLE_PASSWORD) @@ -434,324 +414,358 @@ handle_encrypted_part (MuMsg *msg, GMimeMultipartEncrypted *part, else pw_func = NULL; - err = NULL; - dec = mu_msg_crypto_decrypt_part (part, opts, pw_func, NULL, &err); + dec = mu_msg_crypto_decrypt_part(part, opts, pw_func, NULL, &err); if (err) { - g_warning ("error decrypting part: %s", err->message); - g_clear_error (&err); + g_warning("error decrypting part: %s", err->message); + g_clear_error(&err); } if (dec) { - rv = handle_mime_object (msg, dec, (GMimeObject *) part, - opts, index, TRUE, func, user_data); - g_object_unref (dec); + rv = handle_mime_object(msg, + dec, + (GMimeObject*)part, + opts, + index, + TRUE, + func, + user_data); + g_object_unref(dec); } else { /* On failure to decrypt, list the encrypted part as * an attachment */ - GMimeObject *encrypted; + GMimeObject* encrypted; - encrypted = g_mime_multipart_get_part ( - GMIME_MULTIPART (part), 1); + encrypted = g_mime_multipart_get_part(GMIME_MULTIPART(part), 1); - g_return_val_if_fail (GMIME_IS_PART(encrypted), FALSE); + g_return_val_if_fail(GMIME_IS_PART(encrypted), FALSE); - rv = handle_mime_object (msg, encrypted, (GMimeObject *) part, - opts, index, FALSE, func, user_data); + rv = handle_mime_object(msg, + encrypted, + (GMimeObject*)part, + opts, + index, + FALSE, + func, + user_data); } return rv; } static gboolean -looks_like_text_body_part (GMimeContentType *ctype) +looks_like_text_body_part(GMimeContentType* ctype) { unsigned u; static struct { - const char *type; - const char *subtype; + const char* type; + const char* subtype; } types[] = { - { "text", "plain" }, - { "text", "x-markdown" }, - { "text", "x-diff" }, - { "text", "x-patch" }, - { "application", "x-patch"} - /* possible other types */ + {"text", "plain"}, + {"text", "x-markdown"}, + {"text", "x-diff"}, + {"text", "x-patch"}, + {"application", "x-patch"} + /* possible other types */ }; for (u = 0; u != G_N_ELEMENTS(types); ++u) - if (g_mime_content_type_is_type ( - ctype, types[u].type, types[u].subtype)) + if (g_mime_content_type_is_type(ctype, types[u].type, types[u].subtype)) return TRUE; return FALSE; } - static MuMsgPartSigStatusReport* -copy_status_report_maybe (GObject *obj) +copy_status_report_maybe(GObject* obj) { MuMsgPartSigStatusReport *report, *copy; - report = (MuMsgPartSigStatusReport*) - g_object_get_data (obj, SIG_STATUS_REPORT); + report = (MuMsgPartSigStatusReport*)g_object_get_data(obj, SIG_STATUS_REPORT); if (!report) return NULL; /* nothing to copy */ - copy = g_slice_new0(MuMsgPartSigStatusReport); + copy = g_slice_new0(MuMsgPartSigStatusReport); copy->verdict = report->verdict; if (report->report) - copy->report = g_strdup (report->report); + copy->report = g_strdup(report->report); if (report->signers) - copy->signers = g_strdup (report->signers); + copy->signers = g_strdup(report->signers); return copy; } - - /* call 'func' with information about this MIME-part */ static gboolean -handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent, - MuMsgOptions opts, unsigned *index, gboolean decrypted, - MuMsgPartForeachFunc func, gpointer user_data) +handle_part(MuMsg* msg, + GMimePart* part, + GMimeObject* parent, + MuMsgOptions opts, + unsigned* index, + gboolean decrypted, + MuMsgPartForeachFunc func, + gpointer user_data) { - GMimeContentType *ct; - MuMsgPart msgpart; + GMimeContentType* ct; + MuMsgPart msgpart; - memset (&msgpart, 0, sizeof(MuMsgPart)); + memset(&msgpart, 0, sizeof(MuMsgPart)); - msgpart.size = get_part_size (part); - msgpart.part_type = MU_MSG_PART_TYPE_LEAF; - msgpart.part_type |= get_disposition ((GMimeObject*)part); + msgpart.size = get_part_size(part); + msgpart.part_type = MU_MSG_PART_TYPE_LEAF; + msgpart.part_type |= get_disposition((GMimeObject*)part); if (decrypted) msgpart.part_type |= MU_MSG_PART_TYPE_DECRYPTED; - else if ((opts & MU_MSG_OPTION_DECRYPT) && - GMIME_IS_MULTIPART_ENCRYPTED (parent)) + else if ((opts & MU_MSG_OPTION_DECRYPT) && GMIME_IS_MULTIPART_ENCRYPTED(parent)) msgpart.part_type |= MU_MSG_PART_TYPE_ENCRYPTED; - - ct = g_mime_object_get_content_type ((GMimeObject*)part); + ct = g_mime_object_get_content_type((GMimeObject*)part); if (GMIME_IS_CONTENT_TYPE(ct)) { - msgpart.type = g_mime_content_type_get_media_type (ct); - msgpart.subtype = g_mime_content_type_get_media_subtype (ct); + msgpart.type = g_mime_content_type_get_media_type(ct); + msgpart.subtype = g_mime_content_type_get_media_subtype(ct); /* store in the part_type as well, for quick checking */ - if (looks_like_text_body_part (ct)) + if (looks_like_text_body_part(ct)) msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_PLAIN; - else if (g_mime_content_type_is_type (ct, "text", "html")) + else if (g_mime_content_type_is_type(ct, "text", "html")) msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML; } /* put the verification info in the pgp-signature and every * descendent of a pgp-encrypted part */ msgpart.sig_status_report = NULL; - if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0 || - decrypted) { - msgpart.sig_status_report = - copy_status_report_maybe (G_OBJECT(parent)); + if (g_ascii_strcasecmp(msgpart.subtype, "pgp-signature") == 0 || decrypted) { + msgpart.sig_status_report = copy_status_report_maybe(G_OBJECT(parent)); if (msgpart.sig_status_report) msgpart.part_type |= MU_MSG_PART_TYPE_SIGNED; } - msgpart.data = (gpointer)part; - msgpart.index = (*index)++; + msgpart.data = (gpointer)part; + msgpart.index = (*index)++; - func (msg, &msgpart, user_data); + func(msg, &msgpart, user_data); - mu_msg_part_sig_status_report_destroy (msgpart.sig_status_report); + mu_msg_part_sig_status_report_destroy(msgpart.sig_status_report); return TRUE; } - /* call 'func' with information about this MIME-part */ static gboolean -handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, - GMimeObject *parent, MuMsgOptions opts, unsigned *index, - gboolean decrypted, - MuMsgPartForeachFunc func, gpointer user_data) +handle_message_part(MuMsg* msg, + GMimeMessagePart* mimemsgpart, + GMimeObject* parent, + MuMsgOptions opts, + unsigned* index, + gboolean decrypted, + MuMsgPartForeachFunc func, + gpointer user_data) { MuMsgPart msgpart; - memset (&msgpart, 0, sizeof(MuMsgPart)); + memset(&msgpart, 0, sizeof(MuMsgPart)); - msgpart.type = "message"; - msgpart.subtype = "rfc822"; - msgpart.index = (*index)++; + msgpart.type = "message"; + msgpart.subtype = "rfc822"; + msgpart.index = (*index)++; /* msgpart.size = 0; /\* maybe calculate this? *\/ */ - msgpart.part_type = MU_MSG_PART_TYPE_MESSAGE; - msgpart.part_type |= get_disposition ((GMimeObject*)mimemsgpart); + msgpart.part_type = MU_MSG_PART_TYPE_MESSAGE; + msgpart.part_type |= get_disposition((GMimeObject*)mimemsgpart); - msgpart.data = (gpointer)mimemsgpart; - func (msg, &msgpart, user_data); + msgpart.data = (gpointer)mimemsgpart; + func(msg, &msgpart, user_data); if (opts & MU_MSG_OPTION_RECURSE_RFC822) { - GMimeMessage *mmsg; /* may return NULL for some - * messages */ - mmsg = g_mime_message_part_get_message (mimemsgpart); + GMimeMessage* mmsg; /* may return NULL for some + * messages */ + mmsg = g_mime_message_part_get_message(mimemsgpart); if (mmsg) - return handle_mime_object (msg, - mmsg->mime_part, - parent, - opts, - index, - decrypted, - func, - user_data); + return handle_mime_object(msg, + mmsg->mime_part, + parent, + opts, + index, + decrypted, + func, + user_data); } return TRUE; } static gboolean -handle_multipart (MuMsg *msg, GMimeMultipart *mpart, GMimeObject *parent, - MuMsgOptions opts, unsigned *index, gboolean decrypted, - MuMsgPartForeachFunc func, gpointer user_data) +handle_multipart(MuMsg* msg, + GMimeMultipart* mpart, + GMimeObject* parent, + MuMsgOptions opts, + unsigned* index, + gboolean decrypted, + MuMsgPartForeachFunc func, + gpointer user_data) { - gboolean res; - GMimeObject *part; - guint i; + gboolean res; + GMimeObject* part; + guint i; res = TRUE; for (i = 0; i < mpart->children->len; i++) { - part = (GMimeObject *) mpart->children->pdata[i]; - res &= handle_mime_object (msg, part, parent, - opts, index, decrypted, - func, user_data); + part = (GMimeObject*)mpart->children->pdata[i]; + res &= + handle_mime_object(msg, part, parent, opts, index, decrypted, func, user_data); } return res; } - static gboolean -handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent, - MuMsgOptions opts, unsigned *index, gboolean decrypted, - MuMsgPartForeachFunc func, gpointer user_data) +handle_mime_object(MuMsg* msg, + GMimeObject* mobj, + GMimeObject* parent, + MuMsgOptions opts, + unsigned* index, + gboolean decrypted, + MuMsgPartForeachFunc func, + gpointer user_data) { - if (GMIME_IS_PART (mobj)) - return handle_part - (msg, GMIME_PART(mobj), parent, - opts, index, decrypted, func, user_data); - else if (GMIME_IS_MESSAGE_PART (mobj)) - return handle_message_part - (msg, GMIME_MESSAGE_PART(mobj), - parent, opts, index, decrypted, func, user_data); - else if ((opts & MU_MSG_OPTION_VERIFY) && - GMIME_IS_MULTIPART_SIGNED (mobj)) { - check_signature - (msg, GMIME_MULTIPART_SIGNED (mobj), opts); - return handle_multipart - (msg, GMIME_MULTIPART (mobj), mobj, opts, - index, decrypted, func, user_data); - } else if ((opts & MU_MSG_OPTION_DECRYPT) && - GMIME_IS_MULTIPART_ENCRYPTED (mobj)) - return handle_encrypted_part - (msg, GMIME_MULTIPART_ENCRYPTED (mobj), - opts, index, func, user_data); - else if (GMIME_IS_MULTIPART (mobj)) - return handle_multipart - (msg, GMIME_MULTIPART (mobj), parent, opts, - index, decrypted, func, user_data); + if (GMIME_IS_PART(mobj)) + return handle_part(msg, + GMIME_PART(mobj), + parent, + opts, + index, + decrypted, + func, + user_data); + else if (GMIME_IS_MESSAGE_PART(mobj)) + return handle_message_part(msg, + GMIME_MESSAGE_PART(mobj), + parent, + opts, + index, + decrypted, + func, + user_data); + else if ((opts & MU_MSG_OPTION_VERIFY) && GMIME_IS_MULTIPART_SIGNED(mobj)) { + check_signature(msg, GMIME_MULTIPART_SIGNED(mobj), opts); + return handle_multipart(msg, + GMIME_MULTIPART(mobj), + mobj, + opts, + index, + decrypted, + func, + user_data); + } else if ((opts & MU_MSG_OPTION_DECRYPT) && GMIME_IS_MULTIPART_ENCRYPTED(mobj)) + return handle_encrypted_part(msg, + GMIME_MULTIPART_ENCRYPTED(mobj), + opts, + index, + func, + user_data); + else if (GMIME_IS_MULTIPART(mobj)) + return handle_multipart(msg, + GMIME_MULTIPART(mobj), + parent, + opts, + index, + decrypted, + func, + user_data); return TRUE; } - gboolean -Mu::mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts, - MuMsgPartForeachFunc func, gpointer user_data) +Mu::mu_msg_part_foreach(MuMsg* msg, + MuMsgOptions opts, + MuMsgPartForeachFunc func, + gpointer user_data) { unsigned index; index = 1; - g_return_val_if_fail (msg, FALSE); + g_return_val_if_fail(msg, FALSE); - if (!mu_msg_load_msg_file (msg, NULL)) + if (!mu_msg_load_msg_file(msg, NULL)) return FALSE; - return handle_mime_object (msg, - msg->_file->_mime_msg->mime_part, - (GMimeObject *) msg->_file->_mime_msg, - opts, - &index, - FALSE, - func, - user_data); + return handle_mime_object(msg, + msg->_file->_mime_msg->mime_part, + (GMimeObject*)msg->_file->_mime_msg, + opts, + &index, + FALSE, + func, + user_data); } - static gboolean -write_part_to_fd (GMimePart *part, int fd, GError **err) +write_part_to_fd(GMimePart* part, int fd, GError** err) { - GMimeStream *stream; - GMimeDataWrapper *wrapper; - gboolean rv; + GMimeStream* stream; + GMimeDataWrapper* wrapper; + gboolean rv; - stream = g_mime_stream_fs_new (fd); + stream = g_mime_stream_fs_new(fd); if (!GMIME_IS_STREAM(stream)) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "failed to create stream"); + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, "failed to create stream"); return FALSE; } - g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), FALSE); + g_mime_stream_fs_set_owner(GMIME_STREAM_FS(stream), FALSE); - wrapper = g_mime_part_get_content (part); + wrapper = g_mime_part_get_content(part); if (!GMIME_IS_DATA_WRAPPER(wrapper)) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "failed to create wrapper"); - g_object_unref (stream); + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, "failed to create wrapper"); + g_object_unref(stream); return FALSE; } - g_object_ref (part); /* FIXME: otherwise, the unrefs below - * give errors...*/ + g_object_ref(part); /* FIXME: otherwise, the unrefs below + * give errors...*/ - if (g_mime_data_wrapper_write_to_stream (wrapper, stream) == -1) { + if (g_mime_data_wrapper_write_to_stream(wrapper, stream) == -1) { rv = FALSE; - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "failed to write to stream"); + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, "failed to write to stream"); } else rv = TRUE; /* g_object_unref (wrapper); we don't own it */ - g_object_unref (stream); + g_object_unref(stream); return rv; } - - static gboolean -write_object_to_fd (GMimeObject *obj, int fd, GError **err) +write_object_to_fd(GMimeObject* obj, int fd, GError** err) { - gchar *str; - str = g_mime_object_to_string (obj, NULL); + gchar* str; + str = g_mime_object_to_string(obj, NULL); if (!str) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "could not get string from object"); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "could not get string from object"); return FALSE; } - if (write (fd, str, strlen(str)) == -1) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "failed to write object: %s", - g_strerror(errno)); + if (write(fd, str, strlen(str)) == -1) { + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "failed to write object: %s", + g_strerror(errno)); return FALSE; } return TRUE; } - static gboolean -save_object (GMimeObject *obj, MuMsgOptions opts, const char *fullpath, - GError **err) +save_object(GMimeObject* obj, MuMsgOptions opts, const char* fullpath, GError** err) { - int fd; + int fd; gboolean rv; gboolean use_existing, overwrite; @@ -760,155 +774,164 @@ save_object (GMimeObject *obj, MuMsgOptions opts, const char *fullpath, /* don't try to overwrite when we already have it; useful when * you're sure it's not a different file with the same name */ - if (use_existing && access (fullpath, F_OK) == 0) + if (use_existing && access(fullpath, F_OK) == 0) return TRUE; /* ok, try to create the file */ - fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite); + fd = mu_util_create_writeable_fd(fullpath, 0600, overwrite); if (fd == -1) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, - "could not open '%s' for writing: %s", - fullpath, errno ? g_strerror(errno) : "error"); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "could not open '%s' for writing: %s", + fullpath, + errno ? g_strerror(errno) : "error"); return FALSE; } - if (GMIME_IS_PART (obj)) - rv = write_part_to_fd ((GMimePart*)obj, fd, err); + if (GMIME_IS_PART(obj)) + rv = write_part_to_fd((GMimePart*)obj, fd, err); else - rv = write_object_to_fd (obj, fd, err); + rv = write_object_to_fd(obj, fd, err); - if (close (fd) != 0 && !err) { /* don't write on top of old err */ - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, - "could not close '%s': %s", - fullpath, errno ? g_strerror(errno) : "error"); + if (close(fd) != 0 && !err) { /* don't write on top of old err */ + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "could not close '%s': %s", + fullpath, + errno ? g_strerror(errno) : "error"); return FALSE; } return rv; } - gchar* -Mu::mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts, - const char* targetdir, unsigned index, GError **err) +Mu::mu_msg_part_get_path(MuMsg* msg, + MuMsgOptions opts, + const char* targetdir, + unsigned index, + GError** err) { - char *fname, *filepath; + char * fname, *filepath; GMimeObject* mobj; - g_return_val_if_fail (msg, NULL); + g_return_val_if_fail(msg, NULL); - if (!mu_msg_load_msg_file (msg, NULL)) + if (!mu_msg_load_msg_file(msg, NULL)) return NULL; - mobj = get_mime_object_at_index (msg, opts, index); - if (!mobj){ - mu_util_g_set_error (err, MU_ERROR_GMIME, - "cannot find part %u", index); + mobj = get_mime_object_at_index(msg, opts, index); + if (!mobj) { + mu_util_g_set_error(err, MU_ERROR_GMIME, "cannot find part %u", index); return NULL; } - fname = mime_part_get_filename (mobj, index, TRUE); - filepath = g_build_path (G_DIR_SEPARATOR_S, targetdir ? targetdir : "", - fname, NULL); + fname = mime_part_get_filename(mobj, index, TRUE); + filepath = g_build_path(G_DIR_SEPARATOR_S, targetdir ? targetdir : "", fname, NULL); /* Unref it since it was referenced earlier by * get_mime_object_at_index */ - g_object_unref (mobj); - g_free (fname); + g_object_unref(mobj); + g_free(fname); return filepath; } - - gchar* -Mu::mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, guint partid, - GError **err) +Mu::mu_msg_part_get_cache_path(MuMsg* msg, MuMsgOptions opts, guint partid, GError** err) { - char *dirname, *filepath; + char * dirname, *filepath; const char* path; - g_return_val_if_fail (msg, NULL); + g_return_val_if_fail(msg, NULL); - if (!mu_msg_load_msg_file (msg, NULL)) + if (!mu_msg_load_msg_file(msg, NULL)) return NULL; - path = mu_msg_get_path (msg); + path = mu_msg_get_path(msg); /* g_compute_checksum_for_string may be better, but requires * rel. new glib (2.16) */ - dirname = g_strdup_printf ("%s%c%x%c%u", - mu_util_cache_dir(), G_DIR_SEPARATOR, - g_str_hash (path), G_DIR_SEPARATOR, - partid); + dirname = g_strdup_printf("%s%c%x%c%u", + mu_util_cache_dir(), + G_DIR_SEPARATOR, + g_str_hash(path), + G_DIR_SEPARATOR, + partid); - if (!mu_util_create_dir_maybe (dirname, 0700, FALSE)) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "failed to create dir %s", dirname); - g_free (dirname); + if (!mu_util_create_dir_maybe(dirname, 0700, FALSE)) { + mu_util_g_set_error(err, MU_ERROR_FILE, "failed to create dir %s", dirname); + g_free(dirname); return NULL; } - filepath = mu_msg_part_get_path (msg, opts, dirname, partid, err); - g_free (dirname); + filepath = mu_msg_part_get_path(msg, opts, dirname, partid, err); + g_free(dirname); return filepath; } - gboolean -Mu::mu_msg_part_save (MuMsg *msg, MuMsgOptions opts, - const char *fullpath, guint partidx, GError **err) +Mu::mu_msg_part_save(MuMsg* msg, + MuMsgOptions opts, + const char* fullpath, + guint partidx, + GError** err) { - gboolean rv; - GMimeObject *part; + gboolean rv; + GMimeObject* part; - g_return_val_if_fail (msg, FALSE); - g_return_val_if_fail (fullpath, FALSE); - g_return_val_if_fail (!((opts & MU_MSG_OPTION_OVERWRITE) && - (opts & MU_MSG_OPTION_USE_EXISTING)), FALSE); + g_return_val_if_fail(msg, FALSE); + g_return_val_if_fail(fullpath, FALSE); + g_return_val_if_fail( + !((opts & MU_MSG_OPTION_OVERWRITE) && (opts & MU_MSG_OPTION_USE_EXISTING)), + FALSE); rv = FALSE; - if (!mu_msg_load_msg_file (msg, err)) + if (!mu_msg_load_msg_file(msg, err)) return rv; - part = get_mime_object_at_index (msg, opts, partidx); + part = get_mime_object_at_index(msg, opts, partidx); /* special case: convert a message-part into a message */ - if (GMIME_IS_MESSAGE_PART (part)) - part = (GMimeObject*)g_mime_message_part_get_message - (GMIME_MESSAGE_PART (part)); + if (GMIME_IS_MESSAGE_PART(part)) + part = (GMimeObject*)g_mime_message_part_get_message(GMIME_MESSAGE_PART(part)); if (!part) - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "part %u does not exist", partidx); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "part %u does not exist", + partidx); else if (!GMIME_IS_PART(part) && !GMIME_IS_MESSAGE(part)) - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME, - "unexpected type %s for part %u", - G_OBJECT_TYPE_NAME((GObject*)part), - partidx); + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_GMIME, + "unexpected type %s for part %u", + G_OBJECT_TYPE_NAME((GObject*)part), + partidx); else - rv = save_object (part, opts, fullpath, err); + rv = save_object(part, opts, fullpath, err); g_clear_object(&part); return rv; } - gchar* -Mu::mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, guint partidx, - GError **err) +Mu::mu_msg_part_save_temp(MuMsg* msg, MuMsgOptions opts, guint partidx, GError** err) { - gchar *filepath; + gchar* filepath; - filepath = mu_msg_part_get_cache_path (msg, opts, partidx, err); + filepath = mu_msg_part_get_cache_path(msg, opts, partidx, err); if (!filepath) return NULL; - if (!mu_msg_part_save (msg, opts, filepath, partidx, err)) { - g_free (filepath); + if (!mu_msg_part_save(msg, opts, filepath, partidx, err)) { + g_free(filepath); return NULL; } @@ -916,85 +939,75 @@ Mu::mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, guint partidx, } static gboolean -match_cid (MuMsgPart *mpart, const char *cid) +match_cid(MuMsgPart* mpart, const char* cid) { - const char *this_cid; + const char* this_cid; - this_cid = g_mime_object_get_content_id ((GMimeObject*)mpart->data); + this_cid = g_mime_object_get_content_id((GMimeObject*)mpart->data); - return g_strcmp0 (this_cid, cid) ? TRUE : FALSE; + return g_strcmp0(this_cid, cid) ? TRUE : FALSE; } int -Mu::mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, - const char *sought_cid) +Mu::mu_msg_find_index_for_cid(MuMsg* msg, MuMsgOptions opts, const char* sought_cid) { const char* cid; - g_return_val_if_fail (msg, -1); - g_return_val_if_fail (sought_cid, -1); + g_return_val_if_fail(msg, -1); + g_return_val_if_fail(sought_cid, -1); - if (!mu_msg_load_msg_file (msg, NULL)) + if (!mu_msg_load_msg_file(msg, NULL)) return -1; - cid = g_str_has_prefix (sought_cid, "cid:") ? - sought_cid + 4 : sought_cid; + cid = g_str_has_prefix(sought_cid, "cid:") ? sought_cid + 4 : sought_cid; - return get_matching_part_index (msg, opts, - (MuMsgPartMatchFunc)match_cid, - (gpointer)cid); + return get_matching_part_index(msg, opts, (MuMsgPartMatchFunc)match_cid, (gpointer)cid); } struct _RxMatchData { - GSList *_lst; - const GRegex *_rx; + GSList* _lst; + const GRegex* _rx; guint _idx; }; typedef struct _RxMatchData RxMatchData; - static void -match_filename_rx (MuMsg *msg, MuMsgPart *mpart, RxMatchData *mdata) +match_filename_rx(MuMsg* msg, MuMsgPart* mpart, RxMatchData* mdata) { - char *fname; + char* fname; - fname = mu_msg_part_get_filename (mpart, FALSE); + fname = mu_msg_part_get_filename(mpart, FALSE); if (!fname) return; - if (g_regex_match (mdata->_rx, fname, (GRegexMatchFlags)0, NULL)) - mdata->_lst = g_slist_prepend (mdata->_lst, - GUINT_TO_POINTER(mpart->index)); - g_free (fname); + if (g_regex_match(mdata->_rx, fname, (GRegexMatchFlags)0, NULL)) + mdata->_lst = g_slist_prepend(mdata->_lst, GUINT_TO_POINTER(mpart->index)); + g_free(fname); } - GSList* -Mu::mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern) +Mu::mu_msg_find_files(MuMsg* msg, MuMsgOptions opts, const GRegex* pattern) { RxMatchData mdata; - g_return_val_if_fail (msg, NULL); - g_return_val_if_fail (pattern, NULL); + g_return_val_if_fail(msg, NULL); + g_return_val_if_fail(pattern, NULL); - if (!mu_msg_load_msg_file (msg, NULL)) + if (!mu_msg_load_msg_file(msg, NULL)) return NULL; mdata._lst = NULL; mdata._rx = pattern; mdata._idx = 0; - mu_msg_part_foreach (msg, opts, - (MuMsgPartForeachFunc)match_filename_rx, - &mdata); + mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)match_filename_rx, &mdata); return mdata._lst; } - gboolean -Mu::mu_msg_part_maybe_attachment (MuMsgPart *part) +Mu::mu_msg_part_maybe_attachment(MuMsgPart* part) { - g_return_val_if_fail (part, FALSE); + g_return_val_if_fail(part, FALSE); /* attachments must be leaf parts */ if (!(part->part_type & MU_MSG_PART_TYPE_LEAF)) diff --git a/lib/mu-msg-part.hh b/lib/mu-msg-part.hh index 0c0c51e1..3aa33b53 100644 --- a/lib/mu-msg-part.hh +++ b/lib/mu-msg-part.hh @@ -29,32 +29,32 @@ namespace Mu { #define SIG_STATUS_REPORT "sig-status-report" enum MuMsgPartType { - MU_MSG_PART_TYPE_NONE = 0, + MU_MSG_PART_TYPE_NONE = 0, /* MIME part without children */ - MU_MSG_PART_TYPE_LEAF = 1 << 1, + MU_MSG_PART_TYPE_LEAF = 1 << 1, /* an RFC822 message part? */ - MU_MSG_PART_TYPE_MESSAGE = 1 << 2, + MU_MSG_PART_TYPE_MESSAGE = 1 << 2, /* disposition inline? */ - MU_MSG_PART_TYPE_INLINE = 1 << 3, + MU_MSG_PART_TYPE_INLINE = 1 << 3, /* disposition attachment? */ - MU_MSG_PART_TYPE_ATTACHMENT = 1 << 4, + MU_MSG_PART_TYPE_ATTACHMENT = 1 << 4, /* a signed part? */ - MU_MSG_PART_TYPE_SIGNED = 1 << 5, + MU_MSG_PART_TYPE_SIGNED = 1 << 5, /* an encrypted part? */ - MU_MSG_PART_TYPE_ENCRYPTED = 1 << 6, + MU_MSG_PART_TYPE_ENCRYPTED = 1 << 6, /* a decrypted part? */ - MU_MSG_PART_TYPE_DECRYPTED = 1 << 7, + MU_MSG_PART_TYPE_DECRYPTED = 1 << 7, /* a text/plain part? */ - MU_MSG_PART_TYPE_TEXT_PLAIN = 1 << 8, + MU_MSG_PART_TYPE_TEXT_PLAIN = 1 << 8, /* a text/html part? */ - MU_MSG_PART_TYPE_TEXT_HTML = 1 << 9 + MU_MSG_PART_TYPE_TEXT_HTML = 1 << 9 }; MU_ENABLE_BITOPS(MuMsgPartType); /* the signature status */ enum _MuMsgPartSigStatus { - MU_MSG_PART_SIG_STATUS_UNSIGNED = 0, + MU_MSG_PART_SIG_STATUS_UNSIGNED = 0, MU_MSG_PART_SIG_STATUS_GOOD, MU_MSG_PART_SIG_STATUS_BAD, @@ -64,9 +64,9 @@ enum _MuMsgPartSigStatus { typedef enum _MuMsgPartSigStatus MuMsgPartSigStatus; typedef struct { - MuMsgPartSigStatus verdict; - const char *report; - const char *signers; + MuMsgPartSigStatus verdict; + const char* report; + const char* signers; } MuMsgPartSigStatusReport; /** @@ -74,29 +74,27 @@ typedef struct { * * @param report a MuMsgPartSignatureStatusReport object */ -void mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report); - +void mu_msg_part_sig_status_report_destroy(MuMsgPartSigStatusReport* report); struct _MuMsgPart { - /* index of this message part */ - unsigned index; + unsigned index; /* cid */ /* const char *content_id; */ /* content-type: type/subtype, ie. text/plain */ - const char *type; - const char *subtype; + const char* type; + const char* subtype; /* size of the part; or < 0 if unknown */ - ssize_t size; + ssize_t size; - gpointer data; /* opaque data */ + gpointer data; /* opaque data */ - MuMsgPartType part_type; - MuMsgPartSigStatusReport *sig_status_report; - }; + MuMsgPartType part_type; + MuMsgPartSigStatusReport* sig_status_report; +}; typedef struct _MuMsgPart MuMsgPart; /** @@ -108,8 +106,8 @@ typedef struct _MuMsgPart MuMsgPart; * * @return the file name (free with g_free) */ -char *mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed) - G_GNUC_WARN_UNUSED_RESULT; +char* mu_msg_part_get_filename(MuMsgPart* mpart, + gboolean construct_if_needed) G_GNUC_WARN_UNUSED_RESULT; /** * get appropriate content id for the mime-part @@ -118,9 +116,7 @@ char *mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed) * * @return const content id */ -const gchar* -mu_msg_part_get_content_id (MuMsgPart *mpart) - G_GNUC_WARN_UNUSED_RESULT; +const gchar* mu_msg_part_get_content_id(MuMsgPart* mpart) G_GNUC_WARN_UNUSED_RESULT; /** * get the text in the MuMsgPart (ie. in its GMimePart) @@ -131,9 +127,8 @@ mu_msg_part_get_content_id (MuMsgPart *mpart) * * @return utf8 string for this MIME part, to be freed by caller */ -char* mu_msg_part_get_text (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) - G_GNUC_WARN_UNUSED_RESULT; - +char* +mu_msg_part_get_text(MuMsg* msg, MuMsgPart* part, MuMsgOptions opts) G_GNUC_WARN_UNUSED_RESULT; /** * does this msg part look like an attachment? @@ -142,8 +137,7 @@ char* mu_msg_part_get_text (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) * * @return TRUE if it looks like an attachment, FALSE otherwise */ -gboolean mu_msg_part_maybe_attachment (MuMsgPart *part); - +gboolean mu_msg_part_maybe_attachment(MuMsgPart* part); /** * save a specific attachment to some targetdir @@ -157,10 +151,8 @@ gboolean mu_msg_part_maybe_attachment (MuMsgPart *part); * @return full path to the message part saved or NULL in case or * error; free with g_free */ -gboolean mu_msg_part_save (MuMsg *msg, MuMsgOptions opts, - const char *filepath, guint partidx, - GError **err); - +gboolean +mu_msg_part_save(MuMsg* msg, MuMsgOptions opts, const char* filepath, guint partidx, GError** err); /** * save a message part to a temporary file and return the full path to @@ -173,11 +165,8 @@ gboolean mu_msg_part_save (MuMsg *msg, MuMsgOptions opts, * * @return the full path to the temp file, or NULL in case of error */ -gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, - guint partidx, GError **err) - G_GNUC_WARN_UNUSED_RESULT; - - +gchar* mu_msg_part_save_temp(MuMsg* msg, MuMsgOptions opts, guint partidx, GError** err) + G_GNUC_WARN_UNUSED_RESULT; /** * get a filename for the saving the message part; try the filename @@ -192,11 +181,11 @@ gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, * * @return a filepath (g_free when done with it) or NULL in case of error */ -gchar* mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts, - const char* targetdir, - guint partidx, GError **err) - G_GNUC_WARN_UNUSED_RESULT; - +gchar* mu_msg_part_get_path(MuMsg* msg, + MuMsgOptions opts, + const char* targetdir, + guint partidx, + GError** err) G_GNUC_WARN_UNUSED_RESULT; /** * get a full path name for a file for saving the message part INDEX; @@ -212,10 +201,8 @@ gchar* mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts, * * @return a filepath (g_free when done with it) or NULL in case of error */ -gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, - guint partidx, GError **err) - G_GNUC_WARN_UNUSED_RESULT; - +gchar* mu_msg_part_get_cache_path(MuMsg* msg, MuMsgOptions opts, guint partidx, GError** err) + G_GNUC_WARN_UNUSED_RESULT; /** * get the part index for the message part with a certain content-id @@ -225,9 +212,7 @@ gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, * * @return the part index number of the found part, or -1 if it was not found */ -int mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, const char* content_id); - - +int mu_msg_find_index_for_cid(MuMsg* msg, MuMsgOptions opts, const char* content_id); /** * retrieve a list of indices for mime-parts with filenames matching a regex @@ -240,11 +225,9 @@ int mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, const char* conten * indices are the GPOINTER_TO_UINT(lst->data) of the list. They must * be freed with g_slist_free */ -GSList* mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern); - - -typedef void (*MuMsgPartForeachFunc) (MuMsg *msg, MuMsgPart*, gpointer); +GSList* mu_msg_find_files(MuMsg* msg, MuMsgOptions opts, const GRegex* pattern); +typedef void (*MuMsgPartForeachFunc)(MuMsg* msg, MuMsgPart*, gpointer); /** * call a function for each of the mime part in a message @@ -257,8 +240,8 @@ typedef void (*MuMsgPartForeachFunc) (MuMsg *msg, MuMsgPart*, gpointer); * * @return FALSE in case of error, TRUE otherwise */ -gboolean mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts, - MuMsgPartForeachFunc func, gpointer user_data); +gboolean +mu_msg_part_foreach(MuMsg* msg, MuMsgOptions opts, MuMsgPartForeachFunc func, gpointer user_data); } // namespace Mu diff --git a/lib/mu-msg-priv.hh b/lib/mu-msg-priv.hh index 21c3f5a6..43aa83dd 100644 --- a/lib/mu-msg-priv.hh +++ b/lib/mu-msg-priv.hh @@ -31,34 +31,31 @@ namespace Mu { struct MuMsgFile { - GMimeMessage *_mime_msg; - time_t _timestamp; - size_t _size; - char *_path; - char *_maildir; - char *_sha1; + GMimeMessage* _mime_msg; + time_t _timestamp; + size_t _size; + char* _path; + char* _maildir; + char* _sha1; }; - /* we put the the MuMsg definition in this separate -priv file, so we * can split the mu_msg implementations over separate files */ struct MuMsg { - - guint _refcount; + guint _refcount; /* our two backend */ - MuMsgFile *_file; /* based on GMime, ie. a file on disc */ - MuMsgDoc *_doc; /* based on Xapian::Document */ + MuMsgFile* _file; /* based on GMime, ie. a file on disc */ + MuMsgDoc* _doc; /* based on Xapian::Document */ /* lists where we push allocated strings / GSLists of string * so we can free them when the struct gets destroyed (and we * can return them as 'const to callers) */ - GSList *_free_later_str; - GSList *_free_later_lst; + GSList* _free_later_str; + GSList* _free_later_lst; }; - /** * convert a GMimePart to a string * @@ -68,9 +65,8 @@ struct MuMsg { * * @return utf8 string for this MIME part, to be freed by caller */ -gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - +gchar* mu_msg_mime_part_to_string(GMimePart* part, + gboolean* err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * Like g_mime_message_foreach, but will recurse into encrypted parts @@ -83,9 +79,10 @@ gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err) * @param err receives error information * */ -void mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt, - GMimeObjectForeachFunc func, - gpointer user_data); +void mu_mime_message_foreach(GMimeMessage* msg, + gboolean decrypt, + GMimeObjectForeachFunc func, + gpointer user_data); /** * callback function to retrieve a password from the user @@ -97,9 +94,10 @@ void mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt, * * @return a newly allocated (g_free'able) string */ -typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *prompt_ctx, - gboolean reprompt, gpointer user_data); - +typedef char* (*MuMsgPartPasswordFunc)(const char* user_id, + const char* prompt_ctx, + gboolean reprompt, + gpointer user_data); /** * verify the signature of a signed message part @@ -110,9 +108,7 @@ typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *promp * * @return a status report object, free with mu_msg_part_sig_status_report_destroy */ -void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, - MuMsgOptions opts, - GError **err); +void mu_msg_crypto_verify_part(GMimeMultipartSigned* sig, MuMsgOptions opts, GError** err); /** * decrypt the given encrypted mime multipart @@ -125,10 +121,11 @@ void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, * * @return the decrypted part, or NULL in case of error */ -GMimeObject* mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts, - MuMsgPartPasswordFunc func, gpointer user_data, - GError **err) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +GMimeObject* mu_msg_crypto_decrypt_part(GMimeMultipartEncrypted* enc, + MuMsgOptions opts, + MuMsgPartPasswordFunc func, + gpointer user_data, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; } // namespace Mu diff --git a/lib/mu-msg-sexp.cc b/lib/mu-msg-sexp.cc index cd011fd6..57138b54 100644 --- a/lib/mu-msg-sexp.cc +++ b/lib/mu-msg-sexp.cc @@ -28,418 +28,388 @@ using namespace Mu; static void -add_prop_nonempty (Sexp::List& list, const char* elm, const GSList *str_lst) +add_prop_nonempty(Sexp::List& list, const char* elm, const GSList* str_lst) { - Sexp::List elms; - while (str_lst) { - elms.add(Sexp::make_string((const char*)str_lst->data)); - str_lst = g_slist_next(str_lst); - } + Sexp::List elms; + while (str_lst) { + elms.add(Sexp::make_string((const char*)str_lst->data)); + str_lst = g_slist_next(str_lst); + } - if (!elms.empty()) - list.add_prop(elm, Sexp::make_list(std::move(elms))); + if (!elms.empty()) + list.add_prop(elm, Sexp::make_list(std::move(elms))); } static void -add_prop_nonempty (Sexp::List& list, const char* name, const char *str) +add_prop_nonempty(Sexp::List& list, const char* name, const char* str) { - if (str && str[0]) - list.add_prop(name, Sexp::make_string(str)); + if (str && str[0]) + list.add_prop(name, Sexp::make_string(str)); } - static Sexp -make_contact_sexp (MuMsgContact *c) +make_contact_sexp(MuMsgContact* c) { - // a cons-pair...perhaps make this a plist too? + // a cons-pair...perhaps make this a plist too? - Sexp::List contact; - if (mu_msg_contact_name(c)) - contact.add(Sexp::make_string(Mu::remove_ctrl(mu_msg_contact_name(c)))); - else - contact.add(Sexp::make_symbol("nil")); + Sexp::List contact; + if (mu_msg_contact_name(c)) + contact.add(Sexp::make_string(Mu::remove_ctrl(mu_msg_contact_name(c)))); + else + contact.add(Sexp::make_symbol("nil")); - contact.add(Sexp::make_symbol(".")); - contact.add(Sexp::make_string(Mu::remove_ctrl(mu_msg_contact_email(c)))); + contact.add(Sexp::make_symbol(".")); + contact.add(Sexp::make_string(Mu::remove_ctrl(mu_msg_contact_email(c)))); - return Sexp::make_list(std::move(contact)); + return Sexp::make_list(std::move(contact)); } static void -add_list_post (Sexp::List& list, MuMsg *msg) +add_list_post(Sexp::List& list, MuMsg* msg) { - /* some mailing lists do not set the reply-to; see pull #1278. So for - * those cases, check the List-Post address and use that instead */ + /* some mailing lists do not set the reply-to; see pull #1278. So for + * those cases, check the List-Post address and use that instead */ - GMatchInfo *minfo; - GRegex *rx; - const char* list_post; + GMatchInfo* minfo; + GRegex* rx; + const char* list_post; - list_post = mu_msg_get_header (msg, "List-Post"); - if (!list_post) - return; + list_post = mu_msg_get_header(msg, "List-Post"); + if (!list_post) + return; - rx = g_regex_new ("?", - G_REGEX_CASELESS, (GRegexMatchFlags)0, NULL); - g_return_if_fail(rx); + rx = g_regex_new("?", + G_REGEX_CASELESS, + (GRegexMatchFlags)0, + NULL); + g_return_if_fail(rx); - if (g_regex_match (rx, list_post, (GRegexMatchFlags)0, &minfo)) { - auto address = (char*)g_match_info_fetch (minfo, 1); - MuMsgContact contact{NULL, address}; - list.add_prop(":list-post", - Sexp::make_list(make_contact_sexp(&contact))); - g_free(address); - } + if (g_regex_match(rx, list_post, (GRegexMatchFlags)0, &minfo)) { + auto address = (char*)g_match_info_fetch(minfo, 1); + MuMsgContact contact{NULL, address}; + list.add_prop(":list-post", Sexp::make_list(make_contact_sexp(&contact))); + g_free(address); + } - g_match_info_free (minfo); - g_regex_unref (rx); + g_match_info_free(minfo); + g_regex_unref(rx); } - struct _ContactData { - Sexp::List from, to, cc, bcc, reply_to; + Sexp::List from, to, cc, bcc, reply_to; }; typedef struct _ContactData ContactData; - static gboolean -each_contact (MuMsgContact *c, ContactData *cdata) +each_contact(MuMsgContact* c, ContactData* cdata) { - switch (mu_msg_contact_type (c)) { - - case MU_MSG_CONTACT_TYPE_FROM: - cdata->from.add(make_contact_sexp(c)); - break; - case MU_MSG_CONTACT_TYPE_TO: - cdata->to.add(make_contact_sexp(c)); - break; - case MU_MSG_CONTACT_TYPE_CC: - cdata->cc.add(make_contact_sexp(c)); - break; - case MU_MSG_CONTACT_TYPE_BCC: - cdata->bcc.add(make_contact_sexp(c)); - break; - case MU_MSG_CONTACT_TYPE_REPLY_TO: - cdata->reply_to.add(make_contact_sexp(c)); - break; - default: - g_return_val_if_reached (FALSE); - return FALSE; - } - return TRUE; + switch (mu_msg_contact_type(c)) { + case MU_MSG_CONTACT_TYPE_FROM: cdata->from.add(make_contact_sexp(c)); break; + case MU_MSG_CONTACT_TYPE_TO: cdata->to.add(make_contact_sexp(c)); break; + case MU_MSG_CONTACT_TYPE_CC: cdata->cc.add(make_contact_sexp(c)); break; + case MU_MSG_CONTACT_TYPE_BCC: cdata->bcc.add(make_contact_sexp(c)); break; + case MU_MSG_CONTACT_TYPE_REPLY_TO: cdata->reply_to.add(make_contact_sexp(c)); break; + default: g_return_val_if_reached(FALSE); return FALSE; + } + return TRUE; } static void -add_prop_nonempty_list(Sexp::List& list, std::string&& name, - Sexp::List&& sexp) +add_prop_nonempty_list(Sexp::List& list, std::string&& name, Sexp::List&& sexp) { - if (sexp.empty()) - return; + if (sexp.empty()) + return; - list.add_prop(std::move(name), - Sexp::make_list(std::move(sexp))); + list.add_prop(std::move(name), Sexp::make_list(std::move(sexp))); } - static void -add_contacts (Sexp::List& list, MuMsg *msg) +add_contacts(Sexp::List& list, MuMsg* msg) { - ContactData cdata{}; - mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact, - &cdata); + ContactData cdata{}; + mu_msg_contact_foreach(msg, (MuMsgContactForeachFunc)each_contact, &cdata); - add_prop_nonempty_list (list, ":from", std::move(cdata.from)); - add_prop_nonempty_list (list, ":to", std::move(cdata.to)); - add_prop_nonempty_list (list, ":cc", std::move(cdata.cc)); - add_prop_nonempty_list (list, ":bcc", std::move(cdata.bcc)); - add_prop_nonempty_list (list, ":reply-to", std::move(cdata.reply_to)); + add_prop_nonempty_list(list, ":from", std::move(cdata.from)); + add_prop_nonempty_list(list, ":to", std::move(cdata.to)); + add_prop_nonempty_list(list, ":cc", std::move(cdata.cc)); + add_prop_nonempty_list(list, ":bcc", std::move(cdata.bcc)); + add_prop_nonempty_list(list, ":reply-to", std::move(cdata.reply_to)); - add_list_post (list, msg); + add_list_post(list, msg); } typedef struct { - Sexp::List flaglist; - MuFlags msgflags; + Sexp::List flaglist; + MuFlags msgflags; } FlagData; static void -each_flag (MuFlags flag, FlagData *fdata) +each_flag(MuFlags flag, FlagData* fdata) { - if (flag & fdata->msgflags) - fdata->flaglist.add(Sexp::make_symbol(mu_flag_name(flag))); + if (flag & fdata->msgflags) + fdata->flaglist.add(Sexp::make_symbol(mu_flag_name(flag))); } static void -add_flags (Sexp::List& list, MuMsg *msg) +add_flags(Sexp::List& list, MuMsg* msg) { - FlagData fdata{}; - fdata.msgflags = mu_msg_get_flags (msg); + FlagData fdata{}; + fdata.msgflags = mu_msg_get_flags(msg); - mu_flags_foreach ((MuFlagsForeachFunc)each_flag, &fdata); - if (!fdata.flaglist.empty()) - list.add_prop(":flags", - Sexp::make_list(std::move(fdata.flaglist))); + mu_flags_foreach((MuFlagsForeachFunc)each_flag, &fdata); + if (!fdata.flaglist.empty()) + list.add_prop(":flags", Sexp::make_list(std::move(fdata.flaglist))); } static char* -get_temp_file (MuMsg *msg, MuMsgOptions opts, unsigned index) +get_temp_file(MuMsg* msg, MuMsgOptions opts, unsigned index) { - char *path; - GError *err; + char* path; + GError* err; - err = NULL; - path = mu_msg_part_get_cache_path (msg, opts, index, &err); - if (!path) - goto errexit; + err = NULL; + path = mu_msg_part_get_cache_path(msg, opts, index, &err); + if (!path) + goto errexit; - if (!mu_msg_part_save (msg, opts, path, index, &err)) - goto errexit; + if (!mu_msg_part_save(msg, opts, path, index, &err)) + goto errexit; - return path; + return path; errexit: - g_warning ("failed to save mime part: %s", - err->message ? err->message : "something went wrong"); - g_clear_error (&err); - g_free (path); + g_warning("failed to save mime part: %s", + err->message ? err->message : "something went wrong"); + g_clear_error(&err); + g_free(path); - return NULL; + return NULL; } static gchar* -get_temp_file_maybe (MuMsg *msg, MuMsgPart *part, MuMsgOptions opts) +get_temp_file_maybe(MuMsg* msg, MuMsgPart* part, MuMsgOptions opts) { - opts = (MuMsgOptions)((int)opts | (int)MU_MSG_OPTION_USE_EXISTING); - if (!(opts & MU_MSG_OPTION_EXTRACT_IMAGES) || - g_ascii_strcasecmp (part->type, "image") != 0) - return NULL; - else - return get_temp_file (msg, opts, part->index); + opts = (MuMsgOptions)((int)opts | (int)MU_MSG_OPTION_USE_EXISTING); + if (!(opts & MU_MSG_OPTION_EXTRACT_IMAGES) || g_ascii_strcasecmp(part->type, "image") != 0) + return NULL; + else + return get_temp_file(msg, opts, part->index); } struct PartInfo { - Sexp::List parts; - MuMsgOptions opts; + Sexp::List parts; + MuMsgOptions opts; }; static void -sig_verdict (Sexp::List& partlist, MuMsgPart *mpart) +sig_verdict(Sexp::List& partlist, MuMsgPart* mpart) { - MuMsgPartSigStatusReport *report = mpart->sig_status_report; - if (!report) - return; + MuMsgPartSigStatusReport* report = mpart->sig_status_report; + if (!report) + return; #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" - switch (report->verdict) { - case MU_MSG_PART_SIG_STATUS_GOOD: - partlist.add_prop(":signature", Sexp::make_symbol("verified")); - break; - case MU_MSG_PART_SIG_STATUS_BAD: - partlist.add_prop(":signature", Sexp::make_symbol("bad")); - break; - case MU_MSG_PART_SIG_STATUS_ERROR: - partlist.add_prop(":signature", Sexp::make_symbol("unverified")); - break; - default: - break; - } +#pragma GCC diagnostic ignored "-Wswitch-enum" + switch (report->verdict) { + case MU_MSG_PART_SIG_STATUS_GOOD: + partlist.add_prop(":signature", Sexp::make_symbol("verified")); + break; + case MU_MSG_PART_SIG_STATUS_BAD: + partlist.add_prop(":signature", Sexp::make_symbol("bad")); + break; + case MU_MSG_PART_SIG_STATUS_ERROR: + partlist.add_prop(":signature", Sexp::make_symbol("unverified")); + break; + default: break; + } #pragma GCC diagnostic pop - if (report->signers) - partlist.add_prop(":signers", Sexp::make_string(report->signers)); + if (report->signers) + partlist.add_prop(":signers", Sexp::make_string(report->signers)); } static void -dec_verdict (Sexp::List& partlist, MuMsgPart *mpart) +dec_verdict(Sexp::List& partlist, MuMsgPart* mpart) { - if (mpart->part_type & MU_MSG_PART_TYPE_DECRYPTED) - partlist.add_prop(":decryption", Sexp::make_symbol("succeeded")); - else if (mpart->part_type & MU_MSG_PART_TYPE_ENCRYPTED) - partlist.add_prop(":decryption", Sexp::make_symbol("failed")); + if (mpart->part_type & MU_MSG_PART_TYPE_DECRYPTED) + partlist.add_prop(":decryption", Sexp::make_symbol("succeeded")); + else if (mpart->part_type & MU_MSG_PART_TYPE_ENCRYPTED) + partlist.add_prop(":decryption", Sexp::make_symbol("failed")); } - static Sexp -make_part_types (MuMsgPartType ptype) +make_part_types(MuMsgPartType ptype) { - struct PartTypes { - MuMsgPartType ptype; - const char* name; - } ptypes[] = { - { MU_MSG_PART_TYPE_LEAF, "leaf" }, - { MU_MSG_PART_TYPE_MESSAGE, "message" }, - { MU_MSG_PART_TYPE_INLINE, "inline" }, - { MU_MSG_PART_TYPE_ATTACHMENT, "attachment" }, - { MU_MSG_PART_TYPE_SIGNED, "signed" }, - { MU_MSG_PART_TYPE_ENCRYPTED, "encrypted" } - }; + struct PartTypes { + MuMsgPartType ptype; + const char* name; + } ptypes[] = {{MU_MSG_PART_TYPE_LEAF, "leaf"}, + {MU_MSG_PART_TYPE_MESSAGE, "message"}, + {MU_MSG_PART_TYPE_INLINE, "inline"}, + {MU_MSG_PART_TYPE_ATTACHMENT, "attachment"}, + {MU_MSG_PART_TYPE_SIGNED, "signed"}, + {MU_MSG_PART_TYPE_ENCRYPTED, "encrypted"}}; - Sexp::List list; - for (auto u = 0U; u!= G_N_ELEMENTS(ptypes); ++u) - if (ptype & ptypes[u].ptype) - list.add(Sexp::make_symbol(ptypes[u].name)); + Sexp::List list; + for (auto u = 0U; u != G_N_ELEMENTS(ptypes); ++u) + if (ptype & ptypes[u].ptype) + list.add(Sexp::make_symbol(ptypes[u].name)); - return Sexp::make_list(std::move(list)); + return Sexp::make_list(std::move(list)); } static void -each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) +each_part(MuMsg* msg, MuMsgPart* part, PartInfo* pinfo) { - auto mimetype = format("%s/%s", + auto mimetype = format("%s/%s", part->type ? part->type : "application", part->subtype ? part->subtype : "octet-stream"); - auto maybe_attach = Sexp::make_symbol(mu_msg_part_maybe_attachment (part) ? - "t" : "nil"); - Sexp::List partlist; + auto maybe_attach = Sexp::make_symbol(mu_msg_part_maybe_attachment(part) ? "t" : "nil"); + Sexp::List partlist; - partlist.add_prop(":index", Sexp::make_number(part->index)); - partlist.add_prop(":mime-type", Sexp::make_string(mimetype)); - partlist.add_prop(":size", Sexp::make_number(part->size)); + partlist.add_prop(":index", Sexp::make_number(part->index)); + partlist.add_prop(":mime-type", Sexp::make_string(mimetype)); + partlist.add_prop(":size", Sexp::make_number(part->size)); - dec_verdict (partlist, part); - sig_verdict (partlist, part); + dec_verdict(partlist, part); + sig_verdict(partlist, part); - if (part->part_type) - partlist.add_prop(":type", make_part_types(part->part_type)); + if (part->part_type) + partlist.add_prop(":type", make_part_types(part->part_type)); - char *fname = mu_msg_part_get_filename (part, TRUE); - if (fname) - partlist.add_prop(":name", Sexp::make_string(fname)) ; - g_free (fname); + char* fname = mu_msg_part_get_filename(part, TRUE); + if (fname) + partlist.add_prop(":name", Sexp::make_string(fname)); + g_free(fname); - if (mu_msg_part_maybe_attachment (part)) - partlist.add_prop(":attachment", Sexp::make_symbol("t")); - const auto cid{ mu_msg_part_get_content_id(part)}; - if (cid) - partlist.add_prop(":cid", Sexp::make_string(cid)); + if (mu_msg_part_maybe_attachment(part)) + partlist.add_prop(":attachment", Sexp::make_symbol("t")); + const auto cid{mu_msg_part_get_content_id(part)}; + if (cid) + partlist.add_prop(":cid", Sexp::make_string(cid)); - char *tempfile = get_temp_file_maybe (msg, part, pinfo->opts); - if (tempfile) - partlist.add_prop (":temp", Sexp::make_string(tempfile)); - g_free (tempfile); + char* tempfile = get_temp_file_maybe(msg, part, pinfo->opts); + if (tempfile) + partlist.add_prop(":temp", Sexp::make_string(tempfile)); + g_free(tempfile); - pinfo->parts.add(Sexp::make_list(std::move(partlist))); -} - - -static void -add_parts (Sexp::List& items, MuMsg *msg, MuMsgOptions opts) -{ - PartInfo pinfo; - pinfo.opts = opts; - - if (mu_msg_part_foreach (msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo) && - !pinfo.parts.empty()) - items.add_prop(":parts", Sexp::make_list(std::move(pinfo.parts))); -} - - -static void -add_message_file_parts (Sexp::List& items, MuMsg *msg, MuMsgOptions opts) -{ - GError *err{NULL}; - if (!mu_msg_load_msg_file (msg, &err)) { - g_warning ("failed to load message file: %s", - err ? err->message : "some error occurred"); - g_clear_error (&err); - return; - } - - add_parts (items, msg, opts); - add_contacts (items, msg); - - /* add the user-agent / x-mailer */ - auto str = mu_msg_get_header (msg, "User-Agent"); - if (!str) - str = mu_msg_get_header (msg, "X-Mailer"); - - add_prop_nonempty (items, ":user-agent", str); - - add_prop_nonempty (items, ":body-txt-params", - mu_msg_get_body_text_content_type_parameters (msg, opts)); - add_prop_nonempty (items, ":body-txt", mu_msg_get_body_text(msg, opts)); - add_prop_nonempty (items, ":body-html", mu_msg_get_body_html(msg, opts)); + pinfo->parts.add(Sexp::make_list(std::move(partlist))); } static void -add_date_and_size (Sexp::List& items, MuMsg *msg) +add_parts(Sexp::List& items, MuMsg* msg, MuMsgOptions opts) { - auto t = mu_msg_get_date (msg); - if (t == (time_t)-1) /* invalid date? */ - t = 0; + PartInfo pinfo; + pinfo.opts = opts; - Sexp::List dlist; - dlist.add(Sexp::make_number((unsigned)(t >> 16))); - dlist.add(Sexp::make_number((unsigned)(t & 0xffff))); - dlist.add(Sexp::make_number(0)); - - items.add_prop(":date", Sexp::make_list(std::move(dlist))); - - auto s = mu_msg_get_size (msg); - if (s == (size_t)-1) /* invalid size? */ - s = 0; - - items.add_prop(":size", Sexp::make_number(s)); + if (mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo) && + !pinfo.parts.empty()) + items.add_prop(":parts", Sexp::make_list(std::move(pinfo.parts))); } - static void -add_tags (Sexp::List& items, MuMsg *msg) +add_message_file_parts(Sexp::List& items, MuMsg* msg, MuMsgOptions opts) { - Sexp::List taglist; - for (auto tags = mu_msg_get_tags(msg); tags; tags = g_slist_next(tags)) - taglist.add(Sexp::make_string((const char*)tags->data)); + GError* err{NULL}; + if (!mu_msg_load_msg_file(msg, &err)) { + g_warning("failed to load message file: %s", + err ? err->message : "some error occurred"); + g_clear_error(&err); + return; + } - if (!taglist.empty()) - items.add_prop(":tags", Sexp::make_list(std::move(taglist))); + add_parts(items, msg, opts); + add_contacts(items, msg); + + /* add the user-agent / x-mailer */ + auto str = mu_msg_get_header(msg, "User-Agent"); + if (!str) + str = mu_msg_get_header(msg, "X-Mailer"); + + add_prop_nonempty(items, ":user-agent", str); + + add_prop_nonempty(items, + ":body-txt-params", + mu_msg_get_body_text_content_type_parameters(msg, opts)); + add_prop_nonempty(items, ":body-txt", mu_msg_get_body_text(msg, opts)); + add_prop_nonempty(items, ":body-html", mu_msg_get_body_html(msg, opts)); } +static void +add_date_and_size(Sexp::List& items, MuMsg* msg) +{ + auto t = mu_msg_get_date(msg); + if (t == (time_t)-1) /* invalid date? */ + t = 0; + + Sexp::List dlist; + dlist.add(Sexp::make_number((unsigned)(t >> 16))); + dlist.add(Sexp::make_number((unsigned)(t & 0xffff))); + dlist.add(Sexp::make_number(0)); + + items.add_prop(":date", Sexp::make_list(std::move(dlist))); + + auto s = mu_msg_get_size(msg); + if (s == (size_t)-1) /* invalid size? */ + s = 0; + + items.add_prop(":size", Sexp::make_number(s)); +} + +static void +add_tags(Sexp::List& items, MuMsg* msg) +{ + Sexp::List taglist; + for (auto tags = mu_msg_get_tags(msg); tags; tags = g_slist_next(tags)) + taglist.add(Sexp::make_string((const char*)tags->data)); + + if (!taglist.empty()) + items.add_prop(":tags", Sexp::make_list(std::move(taglist))); +} Mu::Sexp::List -Mu::msg_to_sexp_list (MuMsg *msg, unsigned docid, MuMsgOptions opts) +Mu::msg_to_sexp_list(MuMsg* msg, unsigned docid, MuMsgOptions opts) { - g_return_val_if_fail (msg, Sexp::List()); - g_return_val_if_fail (!((opts & MU_MSG_OPTION_HEADERS_ONLY) && - (opts & MU_MSG_OPTION_EXTRACT_IMAGES)), - Sexp::List()); - Sexp::List items; + g_return_val_if_fail(msg, Sexp::List()); + g_return_val_if_fail( + !((opts & MU_MSG_OPTION_HEADERS_ONLY) && (opts & MU_MSG_OPTION_EXTRACT_IMAGES)), + Sexp::List()); + Sexp::List items; - if (docid != 0) - items.add_prop(":docid", Sexp::make_number(docid)); + if (docid != 0) + items.add_prop(":docid", Sexp::make_number(docid)); - add_prop_nonempty (items, ":subject", mu_msg_get_subject (msg)); - add_prop_nonempty (items, ":message-id", mu_msg_get_msgid (msg)); - add_prop_nonempty (items, ":mailing-list", mu_msg_get_mailing_list (msg)); - add_prop_nonempty (items, ":path", mu_msg_get_path (msg)); - add_prop_nonempty (items, ":maildir", mu_msg_get_maildir (msg)); + add_prop_nonempty(items, ":subject", mu_msg_get_subject(msg)); + add_prop_nonempty(items, ":message-id", mu_msg_get_msgid(msg)); + add_prop_nonempty(items, ":mailing-list", mu_msg_get_mailing_list(msg)); + add_prop_nonempty(items, ":path", mu_msg_get_path(msg)); + add_prop_nonempty(items, ":maildir", mu_msg_get_maildir(msg)); - items.add_prop(":priority", Sexp::make_symbol(mu_msg_prio_name(mu_msg_get_prio(msg)))); + items.add_prop(":priority", Sexp::make_symbol(mu_msg_prio_name(mu_msg_get_prio(msg)))); - /* in the no-headers-only case (see below) we get a more complete list of contacts, so no - * need to get them here if that's the case */ - if (opts & MU_MSG_OPTION_HEADERS_ONLY) - add_contacts (items, msg); + /* in the no-headers-only case (see below) we get a more complete list of contacts, so no + * need to get them here if that's the case */ + if (opts & MU_MSG_OPTION_HEADERS_ONLY) + add_contacts(items, msg); - add_prop_nonempty (items, ":references", mu_msg_get_references (msg)); - add_prop_nonempty (items, ":in-reply-to", mu_msg_get_header (msg, "In-Reply-To")); + add_prop_nonempty(items, ":references", mu_msg_get_references(msg)); + add_prop_nonempty(items, ":in-reply-to", mu_msg_get_header(msg, "In-Reply-To")); - add_date_and_size (items, msg); - add_flags (items, msg); - add_tags (items, msg); + add_date_and_size(items, msg); + add_flags(items, msg); + add_tags(items, msg); - /* headers are retrieved from the database, views from the - * message file file attr things can only be gotten from the - * file (ie., mu view), not from the database (mu find). */ - if (!(opts & MU_MSG_OPTION_HEADERS_ONLY)) - add_message_file_parts (items, msg, opts); - - return items; + /* headers are retrieved from the database, views from the + * message file file attr things can only be gotten from the + * file (ie., mu view), not from the database (mu find). */ + if (!(opts & MU_MSG_OPTION_HEADERS_ONLY)) + add_message_file_parts(items, msg, opts); + return items; } Mu::Sexp -Mu::msg_to_sexp (MuMsg *msg, unsigned docid, MuMsgOptions opts) +Mu::msg_to_sexp(MuMsg* msg, unsigned docid, MuMsgOptions opts) { - return Sexp::make_list(msg_to_sexp_list(msg, docid, opts)); + return Sexp::make_list(msg_to_sexp_list(msg, docid, opts)); } diff --git a/lib/mu-msg.cc b/lib/mu-msg.cc index ed74e643..feb9f320 100644 --- a/lib/mu-msg.cc +++ b/lib/mu-msg.cc @@ -43,110 +43,110 @@ using namespace Mu; static gboolean _gmime_initialized = FALSE; static void -gmime_init (void) +gmime_init(void) { - g_return_if_fail (!_gmime_initialized); + g_return_if_fail(!_gmime_initialized); g_mime_init(); _gmime_initialized = TRUE; } static void -gmime_uninit (void) +gmime_uninit(void) { - g_return_if_fail (_gmime_initialized); + g_return_if_fail(_gmime_initialized); g_mime_shutdown(); _gmime_initialized = FALSE; } static MuMsg* -msg_new (void) +msg_new(void) { - MuMsg *self; + MuMsg* self; - self = g_new0 (MuMsg, 1); + self = g_new0(MuMsg, 1); self->_refcount = 1; return self; } MuMsg* -Mu::mu_msg_new_from_file (const char *path, const char *mdir, - GError **err) +Mu::mu_msg_new_from_file(const char* path, const char* mdir, GError** err) { - MuMsg *self; - MuMsgFile *msgfile; - gint64 start; + MuMsg* self; + MuMsgFile* msgfile; + gint64 start; - g_return_val_if_fail (path, NULL); + g_return_val_if_fail(path, NULL); - start = g_get_monotonic_time(); + start = g_get_monotonic_time(); if (G_UNLIKELY(!_gmime_initialized)) { - gmime_init (); - atexit (gmime_uninit); + gmime_init(); + atexit(gmime_uninit); } - msgfile = mu_msg_file_new (path, mdir, err); + msgfile = mu_msg_file_new(path, mdir, err); if (!msgfile) return NULL; - self = msg_new (); + self = msg_new(); self->_file = msgfile; - g_debug ("created message from %s in %" G_GINT64_FORMAT " μs", - path, g_get_monotonic_time() - start); + g_debug("created message from %s in %" G_GINT64_FORMAT " μs", + path, + g_get_monotonic_time() - start); return self; } MuMsg* -Mu::mu_msg_new_from_doc (XapianDocument *doc, GError **err) +Mu::mu_msg_new_from_doc(XapianDocument* doc, GError** err) { - MuMsg *self; - MuMsgDoc *msgdoc; + MuMsg* self; + MuMsgDoc* msgdoc; - g_return_val_if_fail (doc, NULL); + g_return_val_if_fail(doc, NULL); if (G_UNLIKELY(!_gmime_initialized)) { - gmime_init (); - atexit (gmime_uninit); + gmime_init(); + atexit(gmime_uninit); } - msgdoc = mu_msg_doc_new (doc, err); + msgdoc = mu_msg_doc_new(doc, err); if (!msgdoc) return NULL; - self = msg_new (); + self = msg_new(); self->_doc = msgdoc; return self; } static void -mu_msg_destroy (MuMsg *self) +mu_msg_destroy(MuMsg* self) { if (!self) return; - mu_msg_file_destroy (self->_file); - mu_msg_doc_destroy (self->_doc); + mu_msg_file_destroy(self->_file); + mu_msg_doc_destroy(self->_doc); { /* cleanup the strings / lists we stored */ - mu_str_free_list (self->_free_later_str); + mu_str_free_list(self->_free_later_str); for (auto cur = self->_free_later_lst; cur; cur = g_slist_next(cur)) g_slist_free_full((GSList*)cur->data, g_free); - g_slist_free (self->_free_later_lst); + g_slist_free(self->_free_later_lst); } - g_free (self); + g_free(self); } MuMsg* -Mu::mu_msg_ref (MuMsg *self) +Mu::mu_msg_ref(MuMsg* self) { - g_return_val_if_fail (self, NULL); + g_return_val_if_fail(self, NULL); ++self->_refcount; @@ -154,489 +154,473 @@ Mu::mu_msg_ref (MuMsg *self) } void -Mu::mu_msg_unref (MuMsg *self) +Mu::mu_msg_unref(MuMsg* self) { - g_return_if_fail (self); - g_return_if_fail (self->_refcount >= 1); + g_return_if_fail(self); + g_return_if_fail(self->_refcount >= 1); if (--self->_refcount == 0) - mu_msg_destroy (self); + mu_msg_destroy(self); } static const gchar* -free_later_str (MuMsg *self, gchar *str) +free_later_str(MuMsg* self, gchar* str) { if (str) - self->_free_later_str = - g_slist_prepend (self->_free_later_str, str); + self->_free_later_str = g_slist_prepend(self->_free_later_str, str); return str; } static const GSList* -free_later_lst (MuMsg *self, GSList *lst) +free_later_lst(MuMsg* self, GSList* lst) { if (lst) - self->_free_later_lst = - g_slist_prepend (self->_free_later_lst, lst); + self->_free_later_lst = g_slist_prepend(self->_free_later_lst, lst); return lst; } /* use this instead of mu_msg_get_path so we don't get into infinite * regress...*/ static const char* -get_path (MuMsg *self) +get_path(MuMsg* self) { - char *val; - gboolean do_free; - - do_free = TRUE; - val = NULL; - - if (self->_doc) - val = mu_msg_doc_get_str_field - (self->_doc, MU_MSG_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); - - /* shouldn't happen */ - if (!val) - g_warning ("%s: message without path?!", __func__); - - return free_later_str (self, val); -} - -/* for some data, we need to read the message file from disk */ -gboolean -Mu::mu_msg_load_msg_file (MuMsg *self, GError **err) -{ - const char *path; - - g_return_val_if_fail (self, FALSE); - - if (self->_file) - return TRUE; /* nothing to do */ - - if (!(path = get_path (self))) { - mu_util_g_set_error (err, MU_ERROR_INTERNAL, - "cannot get path for message"); - return FALSE; - } - - self->_file = mu_msg_file_new (path, NULL, err); - - return (self->_file != NULL); -} - -void -Mu::mu_msg_unload_msg_file (MuMsg *msg) -{ - g_return_if_fail (msg); - - mu_msg_file_destroy (msg->_file); - msg->_file = NULL; -} - -static const GSList* -get_str_list_field (MuMsg *self, MuMsgFieldId mfid) -{ - 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 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); - } - - return free_later_lst (self, val); -} - -static const char* -get_str_field (MuMsg *self, MuMsgFieldId mfid) -{ - char *val; + char* val; gboolean do_free; 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) + val = mu_msg_doc_get_str_field(self->_doc, MU_MSG_FIELD_ID_PATH); - else if (mu_msg_field_gmime (mfid)) { + /* 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); + + /* shouldn't happen */ + if (!val) + g_warning("%s: message without path?!", __func__); + + return free_later_str(self, val); +} + +/* for some data, we need to read the message file from disk */ +gboolean +Mu::mu_msg_load_msg_file(MuMsg* self, GError** err) +{ + const char* path; + + g_return_val_if_fail(self, FALSE); + + if (self->_file) + return TRUE; /* nothing to do */ + + if (!(path = get_path(self))) { + mu_util_g_set_error(err, MU_ERROR_INTERNAL, "cannot get path for message"); + return FALSE; + } + + self->_file = mu_msg_file_new(path, NULL, err); + + return (self->_file != NULL); +} + +void +Mu::mu_msg_unload_msg_file(MuMsg* msg) +{ + g_return_if_fail(msg); + + mu_msg_file_destroy(msg->_file); + msg->_file = NULL; +} + +static const GSList* +get_str_list_field(MuMsg* self, MuMsgFieldId mfid) +{ + 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 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)) + 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_list_field(self->_file, mfid); + } + + return free_later_lst(self, val); +} + +static const char* +get_str_field(MuMsg* self, MuMsgFieldId mfid) +{ + char* val; + gboolean do_free; + + do_free = TRUE; + val = NULL; + + if (self->_doc && mu_msg_field_xapian_value(mfid)) + val = mu_msg_doc_get_str_field(self->_doc, mfid); + + else if (mu_msg_field_gmime(mfid)) { + /* 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); } else val = NULL; - return do_free ? free_later_str (self, val) : val; + return do_free ? free_later_str(self, val) : val; } static gint64 -get_num_field (MuMsg *self, MuMsgFieldId mfid) +get_num_field(MuMsg* self, MuMsgFieldId mfid) { guint64 val; val = -1; - if (self->_doc && mu_msg_field_xapian_value (mfid)) - val = mu_msg_doc_get_num_field (self->_doc, mfid); + if (self->_doc && mu_msg_field_xapian_value(mfid)) + val = mu_msg_doc_get_num_field(self->_doc, mfid); else { /* 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)) + if (!mu_msg_load_msg_file(self, NULL)) return -1; - val = mu_msg_file_get_num_field (self->_file, mfid); + val = mu_msg_file_get_num_field(self->_file, mfid); } return val; } const char* -Mu::mu_msg_get_header (MuMsg *self, const char *header) +Mu::mu_msg_get_header(MuMsg* self, const char* header) { - GError *err; + GError* err; - g_return_val_if_fail (self, NULL); - g_return_val_if_fail (header, NULL); + g_return_val_if_fail(self, NULL); + g_return_val_if_fail(header, NULL); /* if we don't have a file object yet, we need to * create it from the file on disk */ - err = NULL; - if (!mu_msg_load_msg_file (self, &err)) { - g_warning ("failed to load message file: %s", - err ? err->message : "something went wrong"); - return NULL; - } + err = NULL; + if (!mu_msg_load_msg_file(self, &err)) { + g_warning("failed to load message file: %s", + err ? err->message : "something went wrong"); + return NULL; + } - return free_later_str - (self, mu_msg_file_get_header (self->_file, header)); + return free_later_str(self, mu_msg_file_get_header(self->_file, header)); } time_t -Mu::mu_msg_get_timestamp (MuMsg *self) +Mu::mu_msg_get_timestamp(MuMsg* self) { - const char *path; + const char* path; struct stat statbuf; - g_return_val_if_fail (self, 0); + g_return_val_if_fail(self, 0); if (self->_file) return self->_file->_timestamp; - path = mu_msg_get_path (self); - if (!path || stat (path, &statbuf) < 0) + path = mu_msg_get_path(self); + if (!path || stat(path, &statbuf) < 0) return 0; return statbuf.st_mtime; } const char* -Mu::mu_msg_get_path (MuMsg *self) +Mu::mu_msg_get_path(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_PATH); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_PATH); } const char* -Mu::mu_msg_get_subject (MuMsg *self) +Mu::mu_msg_get_subject(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_SUBJECT); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_SUBJECT); } const char* -Mu::mu_msg_get_msgid (MuMsg *self) +Mu::mu_msg_get_msgid(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_MSGID); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_MSGID); } const char* -Mu::mu_msg_get_mailing_list (MuMsg *self) +Mu::mu_msg_get_mailing_list(MuMsg* self) { - const char *ml; - char *decml; + const char* ml; + char* decml; - g_return_val_if_fail (self, NULL); + g_return_val_if_fail(self, NULL); - ml = get_str_field (self, MU_MSG_FIELD_ID_MAILING_LIST); + ml = get_str_field(self, MU_MSG_FIELD_ID_MAILING_LIST); if (!ml) return NULL; - decml = g_mime_utils_header_decode_text (NULL, ml); + decml = g_mime_utils_header_decode_text(NULL, ml); if (!decml) return NULL; - return free_later_str (self, decml); + return free_later_str(self, decml); } const char* -Mu::mu_msg_get_maildir (MuMsg *self) +Mu::mu_msg_get_maildir(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_MAILDIR); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_MAILDIR); } const char* -Mu::mu_msg_get_from (MuMsg *self) +Mu::mu_msg_get_from(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_FROM); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_FROM); } const char* -Mu::mu_msg_get_to (MuMsg *self) +Mu::mu_msg_get_to(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_TO); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_TO); } const char* -Mu::mu_msg_get_cc (MuMsg *self) +Mu::mu_msg_get_cc(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_CC); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_CC); } const char* -Mu::mu_msg_get_bcc (MuMsg *self) +Mu::mu_msg_get_bcc(MuMsg* self) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, MU_MSG_FIELD_ID_BCC); + g_return_val_if_fail(self, NULL); + return get_str_field(self, MU_MSG_FIELD_ID_BCC); } time_t -Mu::mu_msg_get_date (MuMsg *self) +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); + g_return_val_if_fail(self, (time_t)-1); + return (time_t)get_num_field(self, MU_MSG_FIELD_ID_DATE); } MuFlags -Mu::mu_msg_get_flags (MuMsg *self) +Mu::mu_msg_get_flags(MuMsg* self) { - g_return_val_if_fail (self, MU_FLAG_NONE); - return (MuFlags)get_num_field (self, MU_MSG_FIELD_ID_FLAGS); + g_return_val_if_fail(self, MU_FLAG_NONE); + return (MuFlags)get_num_field(self, MU_MSG_FIELD_ID_FLAGS); } size_t -Mu::mu_msg_get_size (MuMsg *self) +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); + g_return_val_if_fail(self, (size_t)-1); + return (size_t)get_num_field(self, MU_MSG_FIELD_ID_SIZE); } MuMsgPrio -Mu::mu_msg_get_prio (MuMsg *self) +Mu::mu_msg_get_prio(MuMsg* self) { - g_return_val_if_fail (self, MU_MSG_PRIO_NORMAL); - return (MuMsgPrio)get_num_field (self, MU_MSG_FIELD_ID_PRIO); + g_return_val_if_fail(self, MU_MSG_PRIO_NORMAL); + return (MuMsgPrio)get_num_field(self, MU_MSG_FIELD_ID_PRIO); } struct _BodyData { - GString *gstr; + GString* gstr; gboolean want_html; }; typedef struct _BodyData BodyData; static void -accumulate_body (MuMsg *msg, MuMsgPart *mpart, BodyData *bdata) +accumulate_body(MuMsg* msg, MuMsgPart* mpart, BodyData* bdata) { - char *txt; - GMimePart *mimepart; - gboolean has_err, is_plain, is_html; + char* txt; + GMimePart* mimepart; + gboolean has_err, is_plain, is_html; if (!GMIME_IS_PART(mpart->data)) return; - if (mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) + if (mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) return; mimepart = (GMimePart*)mpart->data; - is_html = mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML; - is_plain = mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN; + is_html = mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML; + is_plain = mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN; - txt = NULL; - has_err = TRUE; + txt = NULL; + has_err = TRUE; if ((bdata->want_html && is_html) || (!bdata->want_html && is_plain)) - txt = mu_msg_mime_part_to_string (mimepart, &has_err); + txt = mu_msg_mime_part_to_string(mimepart, &has_err); if (!has_err && txt) - bdata->gstr = g_string_append (bdata->gstr, txt); + bdata->gstr = g_string_append(bdata->gstr, txt); - g_free (txt); + g_free(txt); } static char* -get_body (MuMsg *self, MuMsgOptions opts, gboolean want_html) +get_body(MuMsg* self, MuMsgOptions opts, gboolean want_html) { BodyData bdata; bdata.want_html = want_html; - bdata.gstr = g_string_sized_new (4096); + bdata.gstr = g_string_sized_new(4096); /* wipe out some irrelevant options */ opts &= ~MU_MSG_OPTION_VERIFY; opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; - mu_msg_part_foreach (self, opts, - (MuMsgPartForeachFunc)accumulate_body, - &bdata); + mu_msg_part_foreach(self, opts, (MuMsgPartForeachFunc)accumulate_body, &bdata); if (bdata.gstr->len == 0) { - g_string_free (bdata.gstr, TRUE); + g_string_free(bdata.gstr, TRUE); return NULL; } else - return g_string_free (bdata.gstr, FALSE); + return g_string_free(bdata.gstr, FALSE); } typedef struct { - GMimeContentType *ctype; - gboolean want_html; + GMimeContentType* ctype; + gboolean want_html; } ContentTypeData; static void -find_content_type (MuMsg *msg, MuMsgPart *mpart, ContentTypeData *cdata) +find_content_type(MuMsg* msg, MuMsgPart* mpart, ContentTypeData* cdata) { - GMimePart *wanted; + GMimePart* wanted; if (!GMIME_IS_PART(mpart->data)) return; /* text-like attachments are included when in text-mode */ - if (!cdata->want_html && - (mpart->part_type & MU_MSG_PART_TYPE_TEXT_PLAIN)) + 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)) + else if (!(mpart->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && cdata->want_html && + (mpart->part_type & MU_MSG_PART_TYPE_TEXT_HTML)) wanted = (GMimePart*)mpart->data; else wanted = NULL; if (wanted) - cdata->ctype = g_mime_object_get_content_type ( - GMIME_OBJECT(wanted)); + cdata->ctype = g_mime_object_get_content_type(GMIME_OBJECT(wanted)); } static const GSList* -get_content_type_parameters (MuMsg *self, MuMsgOptions opts, gboolean want_html) +get_content_type_parameters(MuMsg* self, MuMsgOptions opts, gboolean want_html) { ContentTypeData cdata; cdata.want_html = want_html; - cdata.ctype = NULL; + cdata.ctype = NULL; /* wipe out some irrelevant options */ opts &= ~MU_MSG_OPTION_VERIFY; opts &= ~MU_MSG_OPTION_EXTRACT_IMAGES; - mu_msg_part_foreach (self, opts, - (MuMsgPartForeachFunc)find_content_type, - &cdata); + mu_msg_part_foreach(self, opts, (MuMsgPartForeachFunc)find_content_type, &cdata); if (cdata.ctype) { + GSList* gslist; + GMimeParamList* paramlist; + const GMimeParam* param; + int i, len; - GSList *gslist; - GMimeParamList *paramlist; - const GMimeParam *param; - int i, len; - - gslist = NULL; - paramlist = g_mime_content_type_get_parameters (cdata.ctype); - len = g_mime_param_list_length (paramlist); + gslist = NULL; + paramlist = g_mime_content_type_get_parameters(cdata.ctype); + len = g_mime_param_list_length(paramlist); for (i = 0; i < len; ++i) { - param = g_mime_param_list_get_parameter_at (paramlist, i); - gslist = g_slist_prepend (gslist, g_strdup (param->name)); - gslist = g_slist_prepend (gslist, g_strdup (param->value)); + param = g_mime_param_list_get_parameter_at(paramlist, i); + gslist = g_slist_prepend(gslist, g_strdup(param->name)); + gslist = g_slist_prepend(gslist, g_strdup(param->value)); } - return free_later_lst (self, g_slist_reverse (gslist)); + return free_later_lst(self, g_slist_reverse(gslist)); } return NULL; } const GSList* -Mu::mu_msg_get_body_text_content_type_parameters (MuMsg *self, MuMsgOptions opts) +Mu::mu_msg_get_body_text_content_type_parameters(MuMsg* self, MuMsgOptions opts) { - g_return_val_if_fail (self, NULL); + g_return_val_if_fail(self, NULL); return get_content_type_parameters(self, opts, FALSE); } const char* -Mu::mu_msg_get_body_html (MuMsg *self, MuMsgOptions opts) +Mu::mu_msg_get_body_html(MuMsg* self, MuMsgOptions opts) { - g_return_val_if_fail (self, NULL); - return free_later_str (self, get_body (self, opts, TRUE)); + g_return_val_if_fail(self, NULL); + return free_later_str(self, get_body(self, opts, TRUE)); } const char* -Mu::mu_msg_get_body_text (MuMsg *self, MuMsgOptions opts) +Mu::mu_msg_get_body_text(MuMsg* self, MuMsgOptions opts) { - g_return_val_if_fail (self, NULL); - return free_later_str (self, get_body (self, opts, FALSE)); + g_return_val_if_fail(self, NULL); + return free_later_str(self, get_body(self, opts, FALSE)); } const GSList* -Mu::mu_msg_get_references (MuMsg *self) +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); + g_return_val_if_fail(self, NULL); + return get_str_list_field(self, MU_MSG_FIELD_ID_REFS); } const GSList* -Mu::mu_msg_get_tags (MuMsg *self) +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); + g_return_val_if_fail(self, NULL); + return get_str_list_field(self, MU_MSG_FIELD_ID_TAGS); } const char* -Mu::mu_msg_get_field_string (MuMsg *self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_string(MuMsg* self, MuMsgFieldId mfid) { - g_return_val_if_fail (self, NULL); - return get_str_field (self, mfid); + g_return_val_if_fail(self, NULL); + return get_str_field(self, mfid); } const GSList* -Mu::mu_msg_get_field_string_list (MuMsg *self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_string_list(MuMsg* self, MuMsgFieldId mfid) { - g_return_val_if_fail (self, NULL); - return get_str_list_field (self, mfid); + g_return_val_if_fail(self, NULL); + return get_str_list_field(self, mfid); } gint64 -Mu::mu_msg_get_field_numeric (MuMsg *self, MuMsgFieldId mfid) +Mu::mu_msg_get_field_numeric(MuMsg* self, MuMsgFieldId mfid) { - g_return_val_if_fail (self, -1); - return get_num_field (self, mfid); + g_return_val_if_fail(self, -1); + return get_num_field(self, mfid); } static gboolean -fill_contact (MuMsgContact *self, InternetAddress *addr, - MuMsgContactType ctype) +fill_contact(MuMsgContact* self, InternetAddress* addr, MuMsgContactType ctype) { if (!addr) return FALSE; - self->full_address = internet_address_to_string ( - addr, NULL, FALSE); + self->full_address = internet_address_to_string(addr, NULL, FALSE); - self->name = internet_address_get_name (addr); - if (mu_str_is_empty (self->name)) { + self->name = internet_address_get_name(addr); + if (mu_str_is_empty(self->name)) { self->name = NULL; } @@ -646,10 +630,9 @@ fill_contact (MuMsgContact *self, InternetAddress *addr, * check, g_mime hits an assert */ if (INTERNET_ADDRESS_IS_MAILBOX(addr)) - self->email= internet_address_mailbox_get_addr - (INTERNET_ADDRESS_MAILBOX(addr)); + self->email = internet_address_mailbox_get_addr(INTERNET_ADDRESS_MAILBOX(addr)); else - self->email = NULL; + self->email = NULL; /* if there's no address, just a name, it's probably a local * address (without @) */ @@ -663,8 +646,10 @@ fill_contact (MuMsgContact *self, InternetAddress *addr, } static void -address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype, - MuMsgContactForeachFunc func, gpointer user_data) +address_list_foreach(InternetAddressList* addrlist, + MuMsgContactType ctype, + MuMsgContactForeachFunc func, + gpointer user_data) { int i, len; @@ -674,16 +659,14 @@ address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype, len = internet_address_list_length(addrlist); for (i = 0; i != len; ++i) { - MuMsgContact contact; - gboolean keep_going; + MuMsgContact contact; + gboolean keep_going; - if (!fill_contact(&contact, - internet_address_list_get_address (addrlist, i), - ctype)) + if (!fill_contact(&contact, internet_address_list_get_address(addrlist, i), ctype)) continue; keep_going = func(&contact, user_data); - g_free ((char*)contact.full_address); + g_free((char*)contact.full_address); if (!keep_going) break; @@ -691,76 +674,71 @@ address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype, } static void -addresses_foreach (const char* addrs, MuMsgContactType ctype, - MuMsgContactForeachFunc func, gpointer user_data) +addresses_foreach(const char* addrs, + MuMsgContactType ctype, + MuMsgContactForeachFunc func, + gpointer user_data) { - InternetAddressList *addrlist; + InternetAddressList* addrlist; if (!addrs) return; - addrlist = internet_address_list_parse (NULL, addrs); + addrlist = internet_address_list_parse(NULL, addrs); if (addrlist) { - address_list_foreach (addrlist, ctype, func, user_data); - g_object_unref (addrlist); + address_list_foreach(addrlist, ctype, func, user_data); + g_object_unref(addrlist); } } static void -msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func, - gpointer user_data) +msg_contact_foreach_file(MuMsg* msg, MuMsgContactForeachFunc func, gpointer user_data) { int i; struct { GMimeAddressType _gmime_type; MuMsgContactType _type; } ctypes[] = { - {GMIME_ADDRESS_TYPE_FROM, MU_MSG_CONTACT_TYPE_FROM}, - {GMIME_ADDRESS_TYPE_REPLY_TO, MU_MSG_CONTACT_TYPE_REPLY_TO}, - {GMIME_ADDRESS_TYPE_TO, MU_MSG_CONTACT_TYPE_TO}, - {GMIME_ADDRESS_TYPE_CC, MU_MSG_CONTACT_TYPE_CC}, - {GMIME_ADDRESS_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC}, + {GMIME_ADDRESS_TYPE_FROM, MU_MSG_CONTACT_TYPE_FROM}, + {GMIME_ADDRESS_TYPE_REPLY_TO, MU_MSG_CONTACT_TYPE_REPLY_TO}, + {GMIME_ADDRESS_TYPE_TO, MU_MSG_CONTACT_TYPE_TO}, + {GMIME_ADDRESS_TYPE_CC, MU_MSG_CONTACT_TYPE_CC}, + {GMIME_ADDRESS_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC}, }; for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) { - InternetAddressList *addrlist; - addrlist = g_mime_message_get_addresses (msg->_file->_mime_msg, - ctypes[i]._gmime_type); - address_list_foreach (addrlist, ctypes[i]._type, func, user_data); + InternetAddressList* addrlist; + addrlist = + g_mime_message_get_addresses(msg->_file->_mime_msg, ctypes[i]._gmime_type); + address_list_foreach(addrlist, ctypes[i]._type, func, user_data); } } static void -msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func, - gpointer user_data) +msg_contact_foreach_doc(MuMsg* msg, MuMsgContactForeachFunc func, gpointer user_data) { - addresses_foreach (mu_msg_get_from (msg), - MU_MSG_CONTACT_TYPE_FROM, func, user_data); - addresses_foreach (mu_msg_get_to (msg), - MU_MSG_CONTACT_TYPE_TO, func, user_data); - addresses_foreach (mu_msg_get_cc (msg), - MU_MSG_CONTACT_TYPE_CC, func, user_data); - addresses_foreach (mu_msg_get_bcc (msg), - MU_MSG_CONTACT_TYPE_BCC, func, user_data); + addresses_foreach(mu_msg_get_from(msg), MU_MSG_CONTACT_TYPE_FROM, func, user_data); + addresses_foreach(mu_msg_get_to(msg), MU_MSG_CONTACT_TYPE_TO, func, user_data); + addresses_foreach(mu_msg_get_cc(msg), MU_MSG_CONTACT_TYPE_CC, func, user_data); + addresses_foreach(mu_msg_get_bcc(msg), MU_MSG_CONTACT_TYPE_BCC, func, user_data); } void -Mu::mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, - gpointer user_data) +Mu::mu_msg_contact_foreach(MuMsg* msg, MuMsgContactForeachFunc func, gpointer user_data) { - g_return_if_fail (msg); - g_return_if_fail (func); + g_return_if_fail(msg); + g_return_if_fail(func); if (msg->_file) - msg_contact_foreach_file (msg, func, user_data); + msg_contact_foreach_file(msg, func, user_data); else if (msg->_doc) - msg_contact_foreach_doc (msg, func, user_data); + msg_contact_foreach_doc(msg, func, user_data); else - g_return_if_reached (); + g_return_if_reached(); } static int -cmp_str (const char *s1, const char *s2) +cmp_str(const char* s1, const char* s2) { if (s1 == s2) return 0; @@ -780,22 +758,22 @@ cmp_str (const char *s1, const char *s2) /* utf 8 */ { char *u1, *u2; - int diff; + int diff; - u1 = g_utf8_strdown (s1, -1); - u2 = g_utf8_strdown (s2, -1); + u1 = g_utf8_strdown(s1, -1); + u2 = g_utf8_strdown(s2, -1); - diff = g_utf8_collate (u1, u2); + diff = g_utf8_collate(u1, u2); - g_free (u1); - g_free (u2); + g_free(u1); + g_free(u2); return diff; } } static int -cmp_subject (const char* s1, const char *s2) +cmp_subject(const char* s1, const char* s2) { if (s1 == s2) return 0; @@ -804,42 +782,37 @@ cmp_subject (const char* s1, const char *s2) else if (!s2) return 1; - return cmp_str ( - mu_str_subject_normalize (s1), - mu_str_subject_normalize (s2)); + return cmp_str(mu_str_subject_normalize(s1), mu_str_subject_normalize(s2)); } int -Mu::mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid) +Mu::mu_msg_cmp(MuMsg* m1, MuMsg* m2, MuMsgFieldId mfid) { - g_return_val_if_fail (m1, 0); - g_return_val_if_fail (m2, 0); - g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), 0); + g_return_val_if_fail(m1, 0); + g_return_val_if_fail(m2, 0); + g_return_val_if_fail(mu_msg_field_id_is_valid(mfid), 0); /* even though date is a numeric field, we can sort it by its * string repr. in the database, which is much faster */ - if (mfid == MU_MSG_FIELD_ID_DATE || - mu_msg_field_is_string (mfid)) - return cmp_str (get_str_field (m1, mfid), - get_str_field (m2, mfid)); + if (mfid == MU_MSG_FIELD_ID_DATE || mu_msg_field_is_string(mfid)) + return cmp_str(get_str_field(m1, mfid), get_str_field(m2, mfid)); if (mfid == MU_MSG_FIELD_ID_SUBJECT) - return cmp_subject (get_str_field (m1, mfid), - get_str_field (m2, mfid)); + return cmp_subject(get_str_field(m1, mfid), get_str_field(m2, mfid)); /* TODO: note, we cast (potentially > MAXINT to int) */ - if (mu_msg_field_is_numeric (mfid)) + if (mu_msg_field_is_numeric(mfid)) return get_num_field(m1, mfid) - get_num_field(m2, mfid); return 0; /* TODO: handle lists */ } gboolean -Mu::mu_msg_is_readable (MuMsg *self) +Mu::mu_msg_is_readable(MuMsg* self) { - g_return_val_if_fail (self, FALSE); + g_return_val_if_fail(self, FALSE); - return access (mu_msg_get_path (self), R_OK) == 0 ? TRUE : FALSE; + return access(mu_msg_get_path(self), R_OK) == 0 ? TRUE : FALSE; } /* we need do to determine the @@ -848,52 +821,52 @@ Mu::mu_msg_is_readable (MuMsg *self) * that we got */ static char* -get_target_mdir (MuMsg *msg, const char *target_maildir, GError **err) +get_target_mdir(MuMsg* msg, const char* target_maildir, GError** err) { - char *rootmaildir, *rv; - const char *maildir; - gboolean not_top_level; + char * rootmaildir, *rv; + const char* maildir; + gboolean not_top_level; /* maildir is the maildir stored in the message, e.g. '/foo' */ maildir = mu_msg_get_maildir(msg); if (!maildir) { - mu_util_g_set_error (err, MU_ERROR_GMIME, - "message without maildir"); + mu_util_g_set_error(err, MU_ERROR_GMIME, "message without maildir"); return NULL; } /* the 'rootmaildir' is the filesystem path from root to * maildir, ie. /home/user/Maildir/foo */ - rootmaildir = mu_maildir_get_maildir_from_path (mu_msg_get_path(msg)); + rootmaildir = mu_maildir_get_maildir_from_path(mu_msg_get_path(msg)); if (!rootmaildir) { - mu_util_g_set_error (err, MU_ERROR_GMIME, - "cannot determine maildir"); + mu_util_g_set_error(err, MU_ERROR_GMIME, "cannot determine maildir"); return NULL; } /* we do a sanity check: verify that that maildir is a suffix of * rootmaildir;*/ not_top_level = TRUE; - if (!g_str_has_suffix (rootmaildir, maildir) && + if (!g_str_has_suffix(rootmaildir, maildir) && /* special case for the top-level '/' maildir, and * remember not_top_level */ - (not_top_level = (g_strcmp0 (maildir, "/") != 0))) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, - "path is '%s', but maildir is '%s' ('%s')", - rootmaildir, mu_msg_get_maildir(msg), - mu_msg_get_path (msg)); - g_free (rootmaildir); + (not_top_level = (g_strcmp0(maildir, "/") != 0))) { + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE, + "path is '%s', but maildir is '%s' ('%s')", + rootmaildir, + mu_msg_get_maildir(msg), + mu_msg_get_path(msg)); + g_free(rootmaildir); return NULL; } /* if we're not at the top-level, remove the final '/' from * the rootmaildir */ if (not_top_level) - rootmaildir[strlen(rootmaildir) - - strlen (mu_msg_get_maildir(msg))] = '\0'; + rootmaildir[strlen(rootmaildir) - strlen(mu_msg_get_maildir(msg))] = '\0'; - rv = g_strconcat (rootmaildir, target_maildir, NULL); - g_free (rootmaildir); + rv = g_strconcat(rootmaildir, target_maildir, NULL); + g_free(rootmaildir); return rv; } @@ -904,41 +877,46 @@ get_target_mdir (MuMsg *msg, const char *target_maildir, GError **err) * super-paranoid here... */ gboolean -Mu::mu_msg_move_to_maildir (MuMsg *self, const char *maildir, - MuFlags flags, gboolean ignore_dups, - gboolean new_name, GError **err) +Mu::mu_msg_move_to_maildir(MuMsg* self, + const char* maildir, + MuFlags flags, + gboolean ignore_dups, + gboolean new_name, + GError** err) { - char *newfullpath; - char *targetmdir; + char* newfullpath; + char* targetmdir; - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (maildir, FALSE); /* i.e. "/inbox" */ + g_return_val_if_fail(self, FALSE); + g_return_val_if_fail(maildir, FALSE); /* i.e. "/inbox" */ /* targetmdir is the full path to maildir, i.e., * /home/foo/Maildir/inbox */ - targetmdir = get_target_mdir (self, maildir, err); + targetmdir = get_target_mdir(self, maildir, err); if (!targetmdir) return FALSE; - newfullpath = mu_maildir_move_message (mu_msg_get_path (self), - targetmdir, flags, - ignore_dups, new_name, - err); + newfullpath = mu_maildir_move_message(mu_msg_get_path(self), + targetmdir, + flags, + ignore_dups, + new_name, + err); if (!newfullpath) { - g_free (targetmdir); + g_free(targetmdir); return FALSE; } /* clear the old backends */ - mu_msg_doc_destroy (self->_doc); + mu_msg_doc_destroy(self->_doc); self->_doc = NULL; - mu_msg_file_destroy (self->_file); + mu_msg_file_destroy(self->_file); /* and create a new one */ - self->_file = mu_msg_file_new (newfullpath, maildir, err); - g_free (targetmdir); - g_free (newfullpath); + self->_file = mu_msg_file_new(newfullpath, maildir, err); + g_free(targetmdir); + g_free(newfullpath); return self->_file ? TRUE : FALSE; } @@ -948,30 +926,32 @@ Mu::mu_msg_move_to_maildir (MuMsg *self, const char *maildir, * some 3rd party progs such as mbsync */ gboolean -Mu::mu_msg_tickle (MuMsg *self, GError **err) +Mu::mu_msg_tickle(MuMsg* self, GError** err) { - g_return_val_if_fail (self, FALSE); + g_return_val_if_fail(self, FALSE); - return mu_msg_move_to_maildir (self, - mu_msg_get_maildir (self), - mu_msg_get_flags (self), - FALSE, TRUE, err); + return mu_msg_move_to_maildir(self, + mu_msg_get_maildir(self), + mu_msg_get_flags(self), + FALSE, + TRUE, + err); } const char* -Mu::mu_str_flags_s (MuFlags flags) +Mu::mu_str_flags_s(MuFlags flags) { - return mu_flags_to_str_s (flags, MU_FLAG_TYPE_ANY); + return mu_flags_to_str_s(flags, MU_FLAG_TYPE_ANY); } char* -Mu::mu_str_flags (MuFlags flags) +Mu::mu_str_flags(MuFlags flags) { - return g_strdup (mu_str_flags_s(flags)); + return g_strdup(mu_str_flags_s(flags)); } static void -cleanup_contact (char *contact) +cleanup_contact(char* contact) { char *c, *c2; @@ -982,45 +962,45 @@ cleanup_contact (char *contact) /* remove everything between '()' if it's after the 5th pos; * good to cleanup corporate contact address spam... */ - c = g_strstr_len (contact, -1, "("); + c = g_strstr_len(contact, -1, "("); if (c && c - contact > 5) *c = '\0'; - g_strstrip (contact); + g_strstrip(contact); } - /* this is still somewhat simplistic... */ const char* -Mu::mu_str_display_contact_s (const char *str) +Mu::mu_str_display_contact_s(const char* str) { static gchar contact[255]; - gchar *c, *c2; + gchar * c, *c2; str = str ? str : ""; - g_strlcpy (contact, str, sizeof(contact)); + g_strlcpy(contact, str, sizeof(contact)); /* we check for '<', so we can strip out the address stuff in * e.g. 'Hello World , but only if there is * something alphanumeric before the < */ - c = g_strstr_len (contact, -1, "<"); + c = g_strstr_len(contact, -1, "<"); if (c != NULL) { - for (c2 = contact; c2 < c && !(isalnum(*c2)); ++c2); + 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'; } - cleanup_contact (contact); + cleanup_contact(contact); return contact; } char* -Mu::mu_str_display_contact (const char *str) +Mu::mu_str_display_contact(const char* str) { - g_return_val_if_fail (str, NULL); + g_return_val_if_fail(str, NULL); - return g_strdup (mu_str_display_contact_s (str)); + return g_strdup(mu_str_display_contact_s(str)); } diff --git a/lib/mu-msg.hh b/lib/mu-msg.hh index 454a21f4..d0497286 100644 --- a/lib/mu-msg.hh +++ b/lib/mu-msg.hh @@ -34,31 +34,31 @@ struct MuMsg; /* options for various functions */ enum MuMsgOptions { - MU_MSG_OPTION_NONE = 0, -/* 1 << 0 is still free! */ + MU_MSG_OPTION_NONE = 0, + /* 1 << 0 is still free! */ /* for -> sexp conversion */ - MU_MSG_OPTION_HEADERS_ONLY = 1 << 1, - MU_MSG_OPTION_EXTRACT_IMAGES = 1 << 2, + MU_MSG_OPTION_HEADERS_ONLY = 1 << 1, + MU_MSG_OPTION_EXTRACT_IMAGES = 1 << 2, /* below options are for checking signatures; only effective * if mu was built with crypto support */ - MU_MSG_OPTION_VERIFY = 1 << 4, - MU_MSG_OPTION_AUTO_RETRIEVE = 1 << 5, - MU_MSG_OPTION_USE_AGENT = 1 << 6, + MU_MSG_OPTION_VERIFY = 1 << 4, + MU_MSG_OPTION_AUTO_RETRIEVE = 1 << 5, + MU_MSG_OPTION_USE_AGENT = 1 << 6, /* MU_MSG_OPTION_USE_PKCS7 = 1 << 7, /\* gpg is the default *\/ */ /* get password from console if needed */ - MU_MSG_OPTION_CONSOLE_PASSWORD = 1 << 7, + MU_MSG_OPTION_CONSOLE_PASSWORD = 1 << 7, - MU_MSG_OPTION_DECRYPT = 1 << 8, + MU_MSG_OPTION_DECRYPT = 1 << 8, /* misc */ - MU_MSG_OPTION_OVERWRITE = 1 << 9, - MU_MSG_OPTION_USE_EXISTING = 1 << 10, + MU_MSG_OPTION_OVERWRITE = 1 << 9, + MU_MSG_OPTION_USE_EXISTING = 1 << 10, /* recurse into submessages */ - MU_MSG_OPTION_RECURSE_RFC822 = 1 << 11 + MU_MSG_OPTION_RECURSE_RFC822 = 1 << 11 }; MU_ENABLE_BITOPS(MuMsgOptions); @@ -78,10 +78,9 @@ MU_ENABLE_BITOPS(MuMsgOptions); * @return a new MuMsg instance or NULL in case of error; call * 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; - +MuMsg* mu_msg_new_from_file(const char* filepath, + const char* maildir, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * create a new MuMsg* instance based on a Xapian::Document @@ -96,9 +95,8 @@ MuMsg *mu_msg_new_from_file (const char* filepath, const char *maildir, * @return a new MuMsg instance or NULL in case of error; call * 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; - +MuMsg* mu_msg_new_from_doc(XapianDocument* doc, + GError** err) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; /** * if we don't have a message file yet (because this message is @@ -109,8 +107,7 @@ MuMsg *mu_msg_new_from_doc (XapianDocument* doc, GError **err) * * @return TRUE if this succeeded, FALSE in case of error */ -gboolean mu_msg_load_msg_file (MuMsg *msg, GError **err); - +gboolean mu_msg_load_msg_file(MuMsg* msg, GError** err); /** * close the file-backend, if any; this function is for the use case @@ -122,7 +119,7 @@ gboolean mu_msg_load_msg_file (MuMsg *msg, GError **err); * * @param msg a message object */ -void mu_msg_unload_msg_file (MuMsg *msg); +void mu_msg_unload_msg_file(MuMsg* msg); /** * increase the reference count for this message @@ -132,7 +129,7 @@ void mu_msg_unload_msg_file (MuMsg *msg); * @return the message with its reference count increased, or NULL in * case of error. */ -MuMsg *mu_msg_ref (MuMsg *msg); +MuMsg* mu_msg_ref(MuMsg* msg); /** * decrease the reference count for this message. if the reference @@ -140,7 +137,7 @@ MuMsg *mu_msg_ref (MuMsg *msg); * * @param msg a message */ -void mu_msg_unref (MuMsg *msg); +void mu_msg_unref(MuMsg* msg); /** * cache the values from the backend (file or db), so we don't the @@ -148,8 +145,7 @@ void mu_msg_unref (MuMsg *msg); * * @param self a message */ -void mu_msg_cache_values (MuMsg *self); - +void mu_msg_cache_values(MuMsg* self); /** * get the plain text body of this message @@ -161,8 +157,7 @@ void mu_msg_cache_values (MuMsg *self); * such body. the returned string should *not* be modified or freed. * The returned data is in UTF8 or NULL. */ -const char* mu_msg_get_body_text (MuMsg *msg, MuMsgOptions opts); - +const char* mu_msg_get_body_text(MuMsg* msg, MuMsgOptions opts); /** * get the content type parameters for the text body part @@ -174,8 +169,7 @@ const char* mu_msg_get_body_text (MuMsg *msg, MuMsgOptions opts); * NULL in case of error or if there is no such body. the returned string * should *not* be modified or freed. The returned data is in UTF8 or NULL. */ -const GSList* mu_msg_get_body_text_content_type_parameters (MuMsg *self, MuMsgOptions opts); - +const GSList* mu_msg_get_body_text_content_type_parameters(MuMsg* self, MuMsgOptions opts); /** * get the html body of this message @@ -186,7 +180,7 @@ const GSList* mu_msg_get_body_text_content_type_parameters (MuMsg *self, MuMsgOp * @return the html body or NULL in case of error or if there is no * such body. the returned string should *not* be modified or freed. */ -const char* mu_msg_get_body_html (MuMsg *msgMu, MuMsgOptions opts); +const char* mu_msg_get_body_html(MuMsg* msgMu, MuMsgOptions opts); /** * get the sender (From:) of this message @@ -196,8 +190,7 @@ const char* mu_msg_get_body_html (MuMsg *msgMu, MuMsgOptions opts); * @return the sender of this Message or NULL in case of error or if there * is no sender. the returned string should *not* be modified or freed. */ -const char* mu_msg_get_from (MuMsg *msg); - +const char* mu_msg_get_from(MuMsg* msg); /** * get the recipients (To:) of this message @@ -207,8 +200,7 @@ const char* mu_msg_get_from (MuMsg *msg); * @return the sender of this Message or NULL in case of error or if there * are no recipients. the returned string should *not* be modified or freed. */ -const char* mu_msg_get_to (MuMsg *msg); - +const char* mu_msg_get_to(MuMsg* msg); /** * get the carbon-copy recipients (Cc:) of this message @@ -219,7 +211,7 @@ const char* mu_msg_get_to (MuMsg *msg); * there are no such recipients. the returned string should *not* be modified * or freed. */ -const char* mu_msg_get_cc (MuMsg *msg); +const char* mu_msg_get_cc(MuMsg* msg); /** * get the blind carbon-copy recipients (Bcc:) of this message; this @@ -231,7 +223,7 @@ const char* mu_msg_get_cc (MuMsg *msg); * error or if there are no such recipients. the returned string * should *not* be modified or freed. */ -const char* mu_msg_get_bcc (MuMsg *msg); +const char* mu_msg_get_bcc(MuMsg* msg); /** * get the file system path of this message @@ -241,8 +233,7 @@ const char* mu_msg_get_bcc (MuMsg *msg); * @return the path of this Message or NULL in case of error. * the returned string should *not* be modified or freed. */ -const char* mu_msg_get_path (MuMsg *msg); - +const char* mu_msg_get_path(MuMsg* msg); /** * get the maildir this message lives in; ie, if the path is @@ -253,8 +244,7 @@ const char* mu_msg_get_path (MuMsg *msg); * @return the maildir requested or NULL in case of error. The returned * string should *not* be modified or freed. */ -const char* mu_msg_get_maildir (MuMsg *msg); - +const char* mu_msg_get_maildir(MuMsg* msg); /** * get the subject of this message @@ -264,7 +254,7 @@ const char* mu_msg_get_maildir (MuMsg *msg); * @return the subject of this Message or NULL in case of error or if there * is no subject. the returned string should *not* be modified or freed. */ -const char* mu_msg_get_subject (MuMsg *msg); +const char* mu_msg_get_subject(MuMsg* msg); /** * get the Message-Id of this message @@ -275,8 +265,7 @@ const char* mu_msg_get_subject (MuMsg *msg); * or a fake message-id for messages that don't have them, or NULL in * case of error. */ -const char* mu_msg_get_msgid (MuMsg *msg); - +const char* mu_msg_get_msgid(MuMsg* msg); /** * get the mailing list for a message, i.e. the mailing-list @@ -288,8 +277,7 @@ const char* mu_msg_get_msgid (MuMsg *msg); * or NULL in case of error or if there is none. the returned string * should *not* be modified or freed. */ -const char* mu_msg_get_mailing_list (MuMsg *msg); - +const char* mu_msg_get_mailing_list(MuMsg* msg); /** * get the message date/time (the Date: field) as time_t, using UTC @@ -299,7 +287,7 @@ const char* mu_msg_get_mailing_list (MuMsg *msg); * @return message date/time or 0 in case of error or if there * is no such header. */ -time_t mu_msg_get_date (MuMsg *msg); +time_t mu_msg_get_date(MuMsg* msg); /** * get the flags for this message @@ -309,8 +297,7 @@ time_t mu_msg_get_date (MuMsg *msg); * @return the file/content flags as logically OR'd #MuMsgFlags or 0 * if there are none. Non-standard flags are ignored. */ -MuFlags mu_msg_get_flags (MuMsg *msg); - +MuFlags mu_msg_get_flags(MuMsg* msg); /** * get the file size in bytes of this message @@ -319,8 +306,7 @@ MuFlags mu_msg_get_flags (MuMsg *msg); * * @return the filesize */ -size_t mu_msg_get_size (MuMsg *msg); - +size_t mu_msg_get_size(MuMsg* msg); /** * get some field value as string @@ -330,8 +316,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, MuMsgFieldId mfid); /** * get some field value as string-list @@ -341,7 +326,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, MuMsgFieldId mfid); /** * get some field value as string @@ -351,7 +336,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, MuMsgFieldId mfid); /** * get the message priority for this message (MU_MSG_PRIO_LOW, @@ -364,7 +349,7 @@ gint64 mu_msg_get_field_numeric (MuMsg *msg, MuMsgFieldId mfid); * * @return the message priority (!= 0) or 0 in case of error */ -MuMsgPrio mu_msg_get_prio (MuMsg *msg); +MuMsgPrio mu_msg_get_prio(MuMsg* msg); /** * get the timestamp (mtime) for the file containing this message @@ -373,8 +358,7 @@ MuMsgPrio mu_msg_get_prio (MuMsg *msg); * * @return the timestamp or 0 in case of error */ -time_t mu_msg_get_timestamp (MuMsg *msg); - +time_t mu_msg_get_timestamp(MuMsg* msg); /** * get a specific header from the message. This value will _not_ be @@ -385,8 +369,7 @@ time_t mu_msg_get_timestamp (MuMsg *msg); * * @return a header string which is valid as long as this MuMsg is */ -const char* mu_msg_get_header (MuMsg *self, const char *header); - +const char* mu_msg_get_header(MuMsg* self, const char* header); /** * get the list of references (consisting of both the References and @@ -398,7 +381,7 @@ const char* mu_msg_get_header (MuMsg *self, const char *header); * * @return a list with the references for this msg. Don't modify/free */ -const GSList* mu_msg_get_references (MuMsg *msg); +const GSList* mu_msg_get_references(MuMsg* msg); /** * get the list of tags (ie., X-Label) @@ -407,8 +390,7 @@ const GSList* mu_msg_get_references (MuMsg *msg); * * @return a list with the tags for this msg. Don't modify/free */ -const GSList* mu_msg_get_tags (MuMsg *self); - +const GSList* mu_msg_get_tags(MuMsg* self); /** * compare two messages for sorting @@ -420,8 +402,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, MuMsgFieldId mfid); /** * check whether there there's a readable file behind this message @@ -430,8 +411,7 @@ int mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid); * * @return TRUE if the message file is readable, FALSE otherwise */ -gboolean mu_msg_is_readable (MuMsg *self); - +gboolean mu_msg_is_readable(MuMsg* self); /** * move a message to another maildir; note that this does _not_ update @@ -451,10 +431,12 @@ gboolean mu_msg_is_readable (MuMsg *self); * * @return TRUE if it worked, FALSE otherwise */ -gboolean mu_msg_move_to_maildir (MuMsg *msg, const char *maildir, - MuFlags flags, gboolean ignore_dups, - gboolean new_name, - GError **err); +gboolean mu_msg_move_to_maildir(MuMsg* msg, + const char* maildir, + MuFlags flags, + gboolean ignore_dups, + gboolean new_name, + GError** err); /** * Tickle a message -- ie., rename a message to some new semi-random name,while @@ -469,35 +451,32 @@ gboolean mu_msg_move_to_maildir (MuMsg *msg, const char *maildir, * * @return TRUE if it worked, FALSE otherwise */ -gboolean mu_msg_tickle (MuMsg *msg, GError **err); +gboolean mu_msg_tickle(MuMsg* msg, GError** err); +enum _MuMsgContactType { /* Reply-To:? */ + MU_MSG_CONTACT_TYPE_TO = 0, + MU_MSG_CONTACT_TYPE_FROM, + MU_MSG_CONTACT_TYPE_CC, + MU_MSG_CONTACT_TYPE_BCC, + MU_MSG_CONTACT_TYPE_REPLY_TO, -enum _MuMsgContactType { /* Reply-To:? */ - MU_MSG_CONTACT_TYPE_TO = 0, - MU_MSG_CONTACT_TYPE_FROM, - MU_MSG_CONTACT_TYPE_CC, - MU_MSG_CONTACT_TYPE_BCC, - MU_MSG_CONTACT_TYPE_REPLY_TO, - - MU_MSG_CONTACT_TYPE_NUM + MU_MSG_CONTACT_TYPE_NUM }; typedef guint MuMsgContactType; /* not a 'real' contact type */ #define MU_MSG_CONTACT_TYPE_ALL (MU_MSG_CONTACT_TYPE_NUM + 1) -#define mu_msg_contact_type_is_valid(MCT)\ - ((MCT) < MU_MSG_CONTACT_TYPE_NUM) +#define mu_msg_contact_type_is_valid(MCT) ((MCT) < MU_MSG_CONTACT_TYPE_NUM) typedef struct { - const char *name; /**< Foo Bar */ - const char *email; /**< foo@bar.cuux */ - const char *full_address; /**< Foo Bar */ - MuMsgContactType type; /**< MU_MSG_CONTACT_TYPE_{ TO, - CC, BCC, FROM, REPLY_TO} */ + const char* name; /**< Foo Bar */ + const char* email; /**< foo@bar.cuux */ + const char* full_address; /**< Foo Bar */ + MuMsgContactType type; /**< MU_MSG_CONTACT_TYPE_{ TO, + CC, BCC, FROM, REPLY_TO} */ } MuMsgContact; - /** * macro to get the name of a contact * @@ -505,7 +484,7 @@ typedef struct { * * @return the name */ -#define mu_msg_contact_name(ct) ((ct)->name) +#define mu_msg_contact_name(ct) ((ct)->name) /** * macro to get the email address of a contact @@ -523,8 +502,7 @@ typedef struct { * * @return the contact type */ -#define mu_msg_contact_type(ct) ((ct)->type) - +#define mu_msg_contact_type(ct) ((ct)->type) /** * callback function @@ -534,8 +512,7 @@ typedef struct { * * @return TRUE if we should continue the foreach, FALSE otherwise */ -typedef gboolean (*MuMsgContactForeachFunc) (MuMsgContact* contact, - gpointer user_data); +typedef gboolean (*MuMsgContactForeachFunc)(MuMsgContact* contact, gpointer user_data); /** * call a function for each of the contacts in a message; the order is: @@ -547,10 +524,7 @@ typedef gboolean (*MuMsgContactForeachFunc) (MuMsgContact* contact, * @param user_data a user-provide pointer that will be passed to the callback * */ -void mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, - gpointer user_data); - - +void mu_msg_contact_foreach(MuMsg* msg, MuMsgContactForeachFunc func, gpointer user_data); /** * create a 'display contact' from an email header To/Cc/Bcc/From-type address @@ -570,8 +544,8 @@ void mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, * * @return a newly allocated string with a display contact */ -const char* mu_str_display_contact_s (const char *str) G_GNUC_CONST; -char *mu_str_display_contact (const char *str) G_GNUC_WARN_UNUSED_RESULT; +const char* mu_str_display_contact_s(const char* str) G_GNUC_CONST; +char* mu_str_display_contact(const char* str) G_GNUC_WARN_UNUSED_RESULT; /** * get a display string for a given set of flags, OR'ed in @@ -588,10 +562,8 @@ char *mu_str_display_contact (const char *str) G_GNUC_WARN_UNUSED_RESULT; * @return a string representation of the flags; see above * for what to do with it */ -const char* mu_str_flags_s (MuFlags flags) G_GNUC_CONST; -char* mu_str_flags (MuFlags flags) - G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - +const char* mu_str_flags_s(MuFlags flags) G_GNUC_CONST; +char* mu_str_flags(MuFlags flags) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; struct QueryMatch; @@ -615,8 +587,8 @@ struct QueryMatch; * * @return a Mu::Sexp or a Mu::Sexp::List representing the message. */ -Mu::Sexp::List msg_to_sexp_list(MuMsg *msg, unsigned docid, MuMsgOptions ops); -Mu::Sexp msg_to_sexp(MuMsg *msg, unsigned docid, MuMsgOptions ops); -} +Mu::Sexp::List msg_to_sexp_list(MuMsg* msg, unsigned docid, MuMsgOptions ops); +Mu::Sexp msg_to_sexp(MuMsg* msg, unsigned docid, MuMsgOptions ops); +} // namespace Mu #endif /*MU_MSG_HH__*/ diff --git a/lib/mu-parser.cc b/lib/mu-parser.cc index b7104459..5f710ed7 100644 --- a/lib/mu-parser.cc +++ b/lib/mu-parser.cc @@ -37,9 +37,8 @@ using namespace Mu; // -> [field:][lower]..[upper] // -> [field:]/regex/ - -#define BUG(...) Mu::Error (Error::Code::Internal, format("%u: BUG: ",__LINE__) \ - + format(__VA_ARGS__)) +#define BUG(...) \ + Mu::Error(Error::Code::Internal, format("%u: BUG: ", __LINE__) + format(__VA_ARGS__)) /** * Get the "shortcut"/internal fields for the the given fieldstr or empty if there is none @@ -50,187 +49,189 @@ using namespace Mu; * to [<"S","subject">], while "recip" could map to [<"to", "T">, <"cc", "C">, <"bcc", "B">] */ struct FieldInfo { - const std::string field; - const std::string prefix; - bool supports_phrase; - unsigned id; + const std::string field; + const std::string prefix; + bool supports_phrase; + unsigned id; }; using FieldInfoVec = std::vector; using Flags = Parser::Flags; struct Parser::Private { - Private(const Store& store, Flags flags): - store_{store}, flags_{flags} {} + Private(const Store& store, Flags flags) : store_{store}, flags_{flags} {} - std::vector process_regex (const std::string& field, - const std::regex& rx) const; + std::vector process_regex(const std::string& field, + const std::regex& rx) const; - Mu::Tree term_1 (Mu::Tokens& tokens, WarningVec& warnings) const; - Mu::Tree term_2 (Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const; - Mu::Tree factor_1 (Mu::Tokens& tokens, WarningVec& warnings) const; - Mu::Tree factor_2 (Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const; - Mu::Tree unit (Mu::Tokens& tokens, WarningVec& warnings) const; - Mu::Tree data (Mu::Tokens& tokens, WarningVec& warnings) const; - Mu::Tree range (const FieldInfoVec& fields, const std::string& lower, - const std::string& upper, size_t pos, WarningVec& warnings) const; - Mu::Tree regex (const FieldInfoVec& fields, const std::string& v, - size_t pos, WarningVec& warnings) const; - Mu::Tree value (const FieldInfoVec& fields, const std::string& v, - size_t pos, WarningVec& warnings) const; -private: - const Store& store_; - const Flags flags_; + Mu::Tree term_1(Mu::Tokens& tokens, WarningVec& warnings) const; + Mu::Tree term_2(Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const; + Mu::Tree factor_1(Mu::Tokens& tokens, WarningVec& warnings) const; + Mu::Tree factor_2(Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const; + Mu::Tree unit(Mu::Tokens& tokens, WarningVec& warnings) const; + Mu::Tree data(Mu::Tokens& tokens, WarningVec& warnings) const; + Mu::Tree range(const FieldInfoVec& fields, + const std::string& lower, + const std::string& upper, + size_t pos, + WarningVec& warnings) const; + Mu::Tree regex(const FieldInfoVec& fields, + const std::string& v, + size_t pos, + WarningVec& warnings) const; + Mu::Tree value(const FieldInfoVec& fields, + const std::string& v, + size_t pos, + WarningVec& warnings) const; + + private: + const Store& store_; + const Flags flags_; }; static MuMsgFieldId -field_id (const std::string& field) +field_id(const std::string& field) { + if (field.empty()) + return MU_MSG_FIELD_ID_NONE; - if (field.empty()) - return MU_MSG_FIELD_ID_NONE; - - MuMsgFieldId id = mu_msg_field_id_from_name (field.c_str(), FALSE); - if (id != MU_MSG_FIELD_ID_NONE) - return id; - else if (field.length() == 1) - return mu_msg_field_id_from_shortcut (field[0], FALSE); - else - return MU_MSG_FIELD_ID_NONE; + MuMsgFieldId id = mu_msg_field_id_from_name(field.c_str(), FALSE); + if (id != MU_MSG_FIELD_ID_NONE) + return id; + else if (field.length() == 1) + return mu_msg_field_id_from_shortcut(field[0], FALSE); + else + return MU_MSG_FIELD_ID_NONE; } static std::string -process_value (const std::string& field, const std::string& value) +process_value(const std::string& field, const std::string& value) { - const auto id = field_id (field); - if (id == MU_MSG_FIELD_ID_NONE) - return value; - switch(id) { - case MU_MSG_FIELD_ID_PRIO: { - if (!value.empty()) - return std::string(1, value[0]); - } break; + const auto id = field_id(field); + if (id == MU_MSG_FIELD_ID_NONE) + return value; + switch (id) { + case MU_MSG_FIELD_ID_PRIO: { + if (!value.empty()) + return std::string(1, value[0]); + } break; - case MU_MSG_FIELD_ID_FLAGS: { - const auto flag = mu_flag_char_from_name (value.c_str()); - if (flag) - return std::string(1, tolower(flag)); - } break; + case MU_MSG_FIELD_ID_FLAGS: { + const auto flag = mu_flag_char_from_name(value.c_str()); + if (flag) + return std::string(1, tolower(flag)); + } break; - default: - break; - } + default: break; + } - return value; // XXX prio/flags, etc. alias + return value; // XXX prio/flags, etc. alias } static void -add_field (std::vector& fields, MuMsgFieldId id) +add_field(std::vector& fields, MuMsgFieldId id) { - const auto shortcut = mu_msg_field_shortcut(id); - if (!shortcut) - return; // can't be searched + const auto shortcut = mu_msg_field_shortcut(id); + if (!shortcut) + return; // can't be searched - const auto name = mu_msg_field_name (id); - const auto pfx = mu_msg_field_xapian_prefix (id); + const auto name = mu_msg_field_name(id); + const auto pfx = mu_msg_field_xapian_prefix(id); - if (!name || !pfx) - return; + if (!name || !pfx) + return; - fields.push_back ({{name}, {pfx}, - (bool)mu_msg_field_xapian_index(id), - id}); + fields.push_back({{name}, {pfx}, (bool)mu_msg_field_xapian_index(id), id}); } static std::vector -process_field (const std::string& field, Flags flags) +process_field(const std::string& field, Flags flags) { - std::vector fields; - if (any_of(flags & Flags::UnitTest)) { - add_field(fields, MU_MSG_FIELD_ID_MSGID); - return fields; - } + std::vector fields; + if (any_of(flags & Flags::UnitTest)) { + add_field(fields, MU_MSG_FIELD_ID_MSGID); + return fields; + } - if (field == "contact" || field == "recip") { // multi fields - add_field (fields, MU_MSG_FIELD_ID_TO); - add_field (fields, MU_MSG_FIELD_ID_CC); - add_field (fields, MU_MSG_FIELD_ID_BCC); - if (field == "contact") - add_field (fields, MU_MSG_FIELD_ID_FROM); - } else if (field == "") { - add_field (fields, MU_MSG_FIELD_ID_TO); - add_field (fields, MU_MSG_FIELD_ID_CC); - add_field (fields, MU_MSG_FIELD_ID_BCC); - add_field (fields, MU_MSG_FIELD_ID_FROM); - add_field (fields, MU_MSG_FIELD_ID_SUBJECT); - add_field (fields, MU_MSG_FIELD_ID_BODY_TEXT); - } else { - const auto id = field_id (field); - if (id != MU_MSG_FIELD_ID_NONE) - add_field (fields, id); - } + if (field == "contact" || field == "recip") { // multi fields + add_field(fields, MU_MSG_FIELD_ID_TO); + add_field(fields, MU_MSG_FIELD_ID_CC); + add_field(fields, MU_MSG_FIELD_ID_BCC); + if (field == "contact") + add_field(fields, MU_MSG_FIELD_ID_FROM); + } else if (field == "") { + add_field(fields, MU_MSG_FIELD_ID_TO); + add_field(fields, MU_MSG_FIELD_ID_CC); + add_field(fields, MU_MSG_FIELD_ID_BCC); + add_field(fields, MU_MSG_FIELD_ID_FROM); + add_field(fields, MU_MSG_FIELD_ID_SUBJECT); + add_field(fields, MU_MSG_FIELD_ID_BODY_TEXT); + } else { + const auto id = field_id(field); + if (id != MU_MSG_FIELD_ID_NONE) + add_field(fields, id); + } - return fields; + return fields; } static bool -is_range_field (const std::string& field) +is_range_field(const std::string& field) { - const auto id = field_id (field); - if (id == MU_MSG_FIELD_ID_NONE) - return false; - else - return mu_msg_field_is_range_field (id); + const auto id = field_id(field); + if (id == MU_MSG_FIELD_ID_NONE) + return false; + else + return mu_msg_field_is_range_field(id); } struct MyRange { - std::string lower; - std::string upper; + std::string lower; + std::string upper; }; static MyRange -process_range (const std::string& field, const std::string& lower, - const std::string& upper) +process_range(const std::string& field, const std::string& lower, const std::string& upper) { - const auto id = field_id (field); - if (id == MU_MSG_FIELD_ID_NONE) - return { lower, upper }; + const auto id = field_id(field); + if (id == MU_MSG_FIELD_ID_NONE) + return {lower, upper}; - std::string l2 = lower; - std::string u2 = upper; + std::string l2 = lower; + std::string u2 = upper; - if (id == MU_MSG_FIELD_ID_DATE) { - l2 = Mu::date_to_time_t_string (lower, true); - u2 = Mu::date_to_time_t_string (upper, false); - } else if (id == MU_MSG_FIELD_ID_SIZE) { - l2 = Mu::size_to_string (lower, true); - u2 = Mu::size_to_string (upper, false); - } + if (id == MU_MSG_FIELD_ID_DATE) { + l2 = Mu::date_to_time_t_string(lower, true); + u2 = Mu::date_to_time_t_string(upper, false); + } else if (id == MU_MSG_FIELD_ID_SIZE) { + l2 = Mu::size_to_string(lower, true); + u2 = Mu::size_to_string(upper, false); + } - return { l2, u2 }; + return {l2, u2}; } std::vector -Parser::Private::process_regex (const std::string& field, const std::regex& rx) const +Parser::Private::process_regex(const std::string& field, const std::regex& rx) const { - const auto id = field_id (field); - if (id == MU_MSG_FIELD_ID_NONE) - return {}; + const auto id = field_id(field); + if (id == MU_MSG_FIELD_ID_NONE) + return {}; - char pfx[] = { mu_msg_field_shortcut(id), '\0' }; + char pfx[] = {mu_msg_field_shortcut(id), '\0'}; - std::vector terms; - store_.for_each_term(pfx,[&](auto&& str){ - if (std::regex_search(str.c_str() + 1, rx)) // avoid copy - terms.emplace_back(str); - return true; - }); + std::vector terms; + store_.for_each_term(pfx, [&](auto&& str) { + if (std::regex_search(str.c_str() + 1, rx)) // avoid copy + terms.emplace_back(str); + return true; + }); - return terms; + return terms; } static Token -look_ahead (const Mu::Tokens& tokens) +look_ahead(const Mu::Tokens& tokens) { return tokens.front(); } @@ -242,8 +243,10 @@ empty() } Mu::Tree -Parser::Private::value (const FieldInfoVec& fields, const std::string& v, - size_t pos, WarningVec& warnings) const +Parser::Private::value(const FieldInfoVec& fields, + const std::string& v, + size_t pos, + WarningVec& warnings) const { auto val = utf8_flatten(v); @@ -253,42 +256,45 @@ Parser::Private::value (const FieldInfoVec& fields, const std::string& v, if (fields.size() == 1) { const auto item = fields.front(); return Tree({Node::Type::Value, - std::make_unique( - item.field, item.prefix, item.id, - process_value(item.field, val), - item.supports_phrase)}); + std::make_unique(item.field, + item.prefix, + item.id, + process_value(item.field, val), + item.supports_phrase)}); } // a 'multi-field' such as "recip:" Tree tree(Node{Node::Type::OpOr}); - for (const auto& item: fields) - tree.add_child (Tree({Node::Type::Value, - std::make_unique( - item.field, item.prefix, item.id, - process_value(item.field, val), - item.supports_phrase)})); + for (const auto& item : fields) + tree.add_child(Tree({Node::Type::Value, + std::make_unique(item.field, + item.prefix, + item.id, + process_value(item.field, val), + item.supports_phrase)})); return tree; } Mu::Tree -Parser::Private::regex (const FieldInfoVec& fields, const std::string& v, - size_t pos, WarningVec& warnings) const +Parser::Private::regex(const FieldInfoVec& fields, + const std::string& v, + size_t pos, + WarningVec& warnings) const { if (v.length() < 2) throw BUG("expected regexp, got '%s'", v.c_str()); - const auto rxstr = utf8_flatten(v.substr(1, v.length()-2)); + const auto rxstr = utf8_flatten(v.substr(1, v.length() - 2)); - try { - Tree tree(Node{Node::Type::OpOr}); - const auto rx = std::regex (rxstr); - for (const auto& field: fields) { - const auto terms = process_regex (field.field, rx); - for (const auto& term: terms) { - tree.add_child (Tree( - {Node::Type::Value, - std::make_unique(field.field, "", - field.id, term)})); + try { + Tree tree(Node{Node::Type::OpOr}); + const auto rx = std::regex(rxstr); + for (const auto& field : fields) { + const auto terms = process_regex(field.field, rx); + for (const auto& term : terms) { + tree.add_child(Tree( + {Node::Type::Value, + std::make_unique(field.field, "", field.id, term)})); } } @@ -299,97 +305,104 @@ Parser::Private::regex (const FieldInfoVec& fields, const std::string& v, } catch (...) { // fallback - warnings.push_back ({pos, "invalid regexp"}); - return value (fields, v, pos, warnings); + warnings.push_back({pos, "invalid regexp"}); + return value(fields, v, pos, warnings); } } - - Mu::Tree -Parser::Private::range (const FieldInfoVec& fields, const std::string& lower, - const std::string& upper, size_t pos, WarningVec& warnings) const +Parser::Private::range(const FieldInfoVec& fields, + const std::string& lower, + const std::string& upper, + size_t pos, + WarningVec& warnings) const { if (fields.empty()) throw BUG("expected field"); const auto& field = fields.front(); if (!is_range_field(field.field)) - return value (fields, lower + ".." + upper, pos, warnings); + return value(fields, lower + ".." + upper, pos, warnings); - auto prange = process_range (field.field, lower, upper); + auto prange = process_range(field.field, lower, upper); if (prange.lower > prange.upper) - prange = process_range (field.field, upper, lower); + prange = process_range(field.field, upper, lower); return Tree({Node::Type::Range, - std::make_unique(field.field, field.prefix, field.id, - prange.lower, prange.upper)}); + std::make_unique(field.field, + field.prefix, + field.id, + prange.lower, + prange.upper)}); } Mu::Tree -Parser::Private::data (Mu::Tokens& tokens, WarningVec& warnings) const +Parser::Private::data(Mu::Tokens& tokens, WarningVec& warnings) const { const auto token = look_ahead(tokens); if (token.type != Token::Type::Data) - warnings.push_back ({token.pos, "expected: value"}); + warnings.push_back({token.pos, "expected: value"}); tokens.pop_front(); std::string field, val; - const auto col = token.str.find (":"); - if (col != 0 && col != std::string::npos && col != token.str.length()-1) { + const auto col = token.str.find(":"); + if (col != 0 && col != std::string::npos && col != token.str.length() - 1) { field = token.str.substr(0, col); - val = token.str.substr(col + 1); + val = token.str.substr(col + 1); } else val = token.str; - auto fields = process_field (field, flags_); - if (fields.empty()) {// not valid field... - warnings.push_back ({token.pos, format ("invalid field '%s'", field.c_str())}); - fields = process_field ("", flags_); + auto fields = process_field(field, flags_); + if (fields.empty()) { // not valid field... + warnings.push_back({token.pos, format("invalid field '%s'", field.c_str())}); + fields = process_field("", flags_); // fallback, treat the whole of foo:bar as a value - return value (fields, field + ":" + val, token.pos, warnings); + return value(fields, field + ":" + val, token.pos, warnings); } // does it look like a regexp? if (val.length() >= 2) - if (val[0] == '/' && val[val.length()-1] == '/') - return regex (fields, val, token.pos, warnings); + if (val[0] == '/' && val[val.length() - 1] == '/') + return regex(fields, val, token.pos, warnings); // does it look like a range? const auto dotdot = val.find(".."); if (dotdot != std::string::npos) - return range(fields, val.substr(0, dotdot), val.substr(dotdot + 2), - token.pos, warnings); + return range(fields, + val.substr(0, dotdot), + val.substr(dotdot + 2), + token.pos, + warnings); else if (is_range_field(fields.front().field)) { // range field without a range - treat as field:val..val - return range (fields, val, val, token.pos, warnings); + return range(fields, val, val, token.pos, warnings); } // if nothing else, it's a value. - return value (fields, val, token.pos, warnings); + return value(fields, val, token.pos, warnings); } Mu::Tree -Parser::Private::unit (Mu::Tokens& tokens, WarningVec& warnings) const +Parser::Private::unit(Mu::Tokens& tokens, WarningVec& warnings) const { if (tokens.empty()) { - warnings.push_back ({0, "expected: unit"}); + warnings.push_back({0, "expected: unit"}); return empty(); } - const auto token = look_ahead (tokens); + const auto token = look_ahead(tokens); if (token.type == Token::Type::Not) { tokens.pop_front(); Tree tree{{Node::Type::OpNot}}; - tree.add_child(unit (tokens, warnings)); + tree.add_child(unit(tokens, warnings)); return tree; } if (token.type == Token::Type::Open) { tokens.pop_front(); - auto tree = term_1 (tokens, warnings); + auto tree = term_1(tokens, warnings); if (tokens.empty()) warnings.push_back({token.pos, "expected: ')'"}); else { @@ -398,21 +411,18 @@ Parser::Private::unit (Mu::Tokens& tokens, WarningVec& warnings) const tokens.pop_front(); else { warnings.push_back( - {token2.pos, - std::string("expected: ')' but got ") + - token2.str}); + {token2.pos, + std::string("expected: ')' but got ") + token2.str}); } - } return tree; } - return data (tokens, warnings); + return data(tokens, warnings); } Mu::Tree -Parser::Private::factor_2 (Mu::Tokens& tokens, Node::Type& op, - WarningVec& warnings) const +Parser::Private::factor_2(Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const { if (tokens.empty()) return empty(); @@ -420,7 +430,7 @@ Parser::Private::factor_2 (Mu::Tokens& tokens, Node::Type& op, const auto token = look_ahead(tokens); #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (token.type) { case Token::Type::And: { tokens.pop_front(); @@ -433,51 +443,44 @@ Parser::Private::factor_2 (Mu::Tokens& tokens, Node::Type& op, op = Node::Type::OpAnd; // implicit AND break; - default: - return empty(); + default: return empty(); } #pragma GCC diagnostic pop - return factor_1 (tokens, warnings); + return factor_1(tokens, warnings); } - Mu::Tree -Parser::Private::factor_1 (Mu::Tokens& tokens, WarningVec& warnings) const +Parser::Private::factor_1(Mu::Tokens& tokens, WarningVec& warnings) const { - Node::Type op { Node::Type::Invalid }; + Node::Type op{Node::Type::Invalid}; - auto t = unit (tokens, warnings); - auto a2 = factor_2 (tokens, op, warnings); + auto t = unit(tokens, warnings); + auto a2 = factor_2(tokens, op, warnings); if (a2.empty()) return t; - Tree tree {{op}}; + Tree tree{{op}}; tree.add_child(std::move(t)); tree.add_child(std::move(a2)); return tree; } - Mu::Tree -Parser::Private::term_2 (Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const +Parser::Private::term_2(Mu::Tokens& tokens, Node::Type& op, WarningVec& warnings) const { if (tokens.empty()) return empty(); - const auto token = look_ahead (tokens); + const auto token = look_ahead(tokens); #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (token.type) { - case Token::Type::Or: - op = Node::Type::OpOr; - break; - case Token::Type::Xor: - op = Node::Type::OpXor; - break; + case Token::Type::Or: op = Node::Type::OpOr; break; + case Token::Type::Xor: op = Node::Type::OpXor; break; default: if (token.type != Token::Type::Close) warnings.push_back({token.pos, "expected OR|XOR"}); @@ -487,43 +490,42 @@ Parser::Private::term_2 (Mu::Tokens& tokens, Node::Type& op, WarningVec& warning tokens.pop_front(); - return term_1 (tokens, warnings); + return term_1(tokens, warnings); } Mu::Tree -Parser::Private::term_1 (Mu::Tokens& tokens, WarningVec& warnings) const +Parser::Private::term_1(Mu::Tokens& tokens, WarningVec& warnings) const { - Node::Type op { Node::Type::Invalid }; + Node::Type op{Node::Type::Invalid}; - auto t = factor_1 (tokens, warnings); - auto o2 = term_2 (tokens, op, warnings); + auto t = factor_1(tokens, warnings); + auto o2 = term_2(tokens, op, warnings); if (o2.empty()) return t; else { - Tree tree {{op}}; + Tree tree{{op}}; tree.add_child(std::move(t)); tree.add_child(std::move(o2)); return tree; } } -Mu::Parser::Parser(const Store& store, Flags flags): - priv_{std::make_unique(store, flags)} -{} +Mu::Parser::Parser(const Store& store, Flags flags) : priv_{std::make_unique(store, flags)} +{ +} Mu::Parser::~Parser() = default; - Mu::Tree -Mu::Parser::parse (const std::string& expr, WarningVec& warnings) const +Mu::Parser::parse(const std::string& expr, WarningVec& warnings) const { try { - auto tokens = tokenize (expr); - if (tokens.empty()) - return empty (); - else - return priv_->term_1 (tokens, warnings); + auto tokens = tokenize(expr); + if (tokens.empty()) + return empty(); + else + return priv_->term_1(tokens, warnings); } catch (const std::runtime_error& ex) { std::cerr << ex.what() << std::endl; diff --git a/lib/mu-parser.hh b/lib/mu-parser.hh index 3f74e558..16c1d0f1 100644 --- a/lib/mu-parser.hh +++ b/lib/mu-parser.hh @@ -17,7 +17,6 @@ ** 02110-1301, USA. */ - #ifndef __PARSER_HH__ #define __PARSER_HH__ @@ -40,8 +39,8 @@ namespace Mu { * */ struct Warning { - size_t pos{}; /**< pos in string */ - const std::string msg; /**< warning message */ + size_t pos{}; /**< pos in string */ + const std::string msg; /**< warning message */ /** * operator== @@ -50,11 +49,9 @@ struct Warning { * * @return true if rhs is equal to this; false otherwise */ - bool operator==(const Warning& rhs) const { - return pos == rhs.pos && msg == rhs.msg; - } + bool operator==(const Warning& rhs) const { return pos == rhs.pos && msg == rhs.msg; } }; -using WarningVec=std::vector; +using WarningVec = std::vector; /** * operator<< @@ -65,44 +62,42 @@ using WarningVec=std::vector; * @return the updated output stream */ inline std::ostream& -operator<< (std::ostream& os, const Warning& w) +operator<<(std::ostream& os, const Warning& w) { os << w.pos << ":" << w.msg; return os; } class Parser { -public: - enum struct Flags { - None = 0, - UnitTest = 1 << 0 - }; + public: + enum struct Flags { None = 0, UnitTest = 1 << 0 }; - /** - * Construct a query parser object - * - * @param store a store object ptr, or none - */ - Parser(const Store& store, Flags=Flags::None); - /** - * DTOR - * - */ - ~Parser(); + /** + * Construct a query parser object + * + * @param store a store object ptr, or none + */ + Parser(const Store& store, Flags = Flags::None); + /** + * DTOR + * + */ + ~Parser(); - /** - * Parse a query string - * - * @param query a query string - * @param warnings vec to receive warnings - * - * @return a parse-tree - */ + /** + * Parse a query string + * + * @param query a query string + * @param warnings vec to receive warnings + * + * @return a parse-tree + */ - Tree parse (const std::string& query, WarningVec& warnings) const; -private: - struct Private; - std::unique_ptr priv_; + Tree parse(const std::string& query, WarningVec& warnings) const; + + private: + struct Private; + std::unique_ptr priv_; }; MU_ENABLE_BITOPS(Parser::Flags); diff --git a/lib/mu-query-match-deciders.cc b/lib/mu-query-match-deciders.cc index c7e91049..381acbbd 100644 --- a/lib/mu-query-match-deciders.cc +++ b/lib/mu-query-match-deciders.cc @@ -35,191 +35,191 @@ using namespace Mu; // We use the MatchDecider to gather information and use it for both queries. struct MatchDecider : public Xapian::MatchDecider { - MatchDecider (QueryFlags qflags, DeciderInfo &info) : qflags_{qflags}, decider_info_{info} - { - } - /** - * Update the match structure with unreadable/duplicate flags - * - * @param doc a Xapian document. - * - * @return a new QueryMatch object - */ - QueryMatch make_query_match (const Xapian::Document &doc) const - { - QueryMatch qm{}; + MatchDecider(QueryFlags qflags, DeciderInfo& info) : qflags_{qflags}, decider_info_{info} {} + /** + * Update the match structure with unreadable/duplicate flags + * + * @param doc a Xapian document. + * + * @return a new QueryMatch object + */ + QueryMatch make_query_match(const Xapian::Document& doc) const + { + QueryMatch qm{}; - auto msgid{opt_string (doc, MU_MSG_FIELD_ID_MSGID) - .value_or (*opt_string (doc, MU_MSG_FIELD_ID_PATH))}; - if (!decider_info_.message_ids.emplace (std::move (msgid)).second) - qm.flags |= QueryMatch::Flags::Duplicate; + auto msgid{opt_string(doc, MU_MSG_FIELD_ID_MSGID) + .value_or(*opt_string(doc, MU_MSG_FIELD_ID_PATH))}; + if (!decider_info_.message_ids.emplace(std::move(msgid)).second) + qm.flags |= QueryMatch::Flags::Duplicate; - const auto path{opt_string (doc, MU_MSG_FIELD_ID_PATH)}; - if (!path || ::access (path->c_str(), R_OK) != 0) - qm.flags |= QueryMatch::Flags::Unreadable; + const auto path{opt_string(doc, MU_MSG_FIELD_ID_PATH)}; + if (!path || ::access(path->c_str(), R_OK) != 0) + qm.flags |= QueryMatch::Flags::Unreadable; - return qm; - } + return qm; + } - /** - * Should this message be included in the results? - * - * @param qm a query match - * - * @return true or false - */ - bool should_include (const QueryMatch &qm) const - { - if (any_of (qflags_ & QueryFlags::SkipDuplicates) && - any_of (qm.flags & QueryMatch::Flags::Duplicate)) - return false; + /** + * Should this message be included in the results? + * + * @param qm a query match + * + * @return true or false + */ + bool should_include(const QueryMatch& qm) const + { + if (any_of(qflags_ & QueryFlags::SkipDuplicates) && + any_of(qm.flags & QueryMatch::Flags::Duplicate)) + return false; - if (any_of (qflags_ & QueryFlags::SkipUnreadable) && - any_of (qm.flags & QueryMatch::Flags::Unreadable)) - return false; + if (any_of(qflags_ & QueryFlags::SkipUnreadable) && + any_of(qm.flags & QueryMatch::Flags::Unreadable)) + return false; - return true; - } - /** - * Gather thread ids from this match. - * - * @param doc the document (message) - * - */ - void gather_thread_ids (const Xapian::Document &doc) const - { - auto thread_id{opt_string (doc, MU_MSG_FIELD_ID_THREAD_ID)}; - if (thread_id) - decider_info_.thread_ids.emplace (std::move (*thread_id)); - } + return true; + } + /** + * Gather thread ids from this match. + * + * @param doc the document (message) + * + */ + void gather_thread_ids(const Xapian::Document& doc) const + { + auto thread_id{opt_string(doc, MU_MSG_FIELD_ID_THREAD_ID)}; + if (thread_id) + decider_info_.thread_ids.emplace(std::move(*thread_id)); + } - protected: - const QueryFlags qflags_; - DeciderInfo & decider_info_; + protected: + const QueryFlags qflags_; + DeciderInfo& decider_info_; - private: - Option opt_string (const Xapian::Document &doc, MuMsgFieldId id) const noexcept - try { - auto &&val{doc.get_value (id)}; - return val.empty() ? Nothing : Some (val); - } - MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing); + private: + Option opt_string(const Xapian::Document& doc, MuMsgFieldId id) const noexcept + { + std::string val = xapian_try([&] { return doc.get_value(id); }, std::string{""}); + if (val.empty()) + return Nothing; + else + return Some(std::move(val)); + } }; struct MatchDeciderLeader final : public MatchDecider { - MatchDeciderLeader (QueryFlags qflags, DeciderInfo &info) : MatchDecider (qflags, info) {} - /** - * operator() - * - * This receives the documents considered during a Xapian query, and - * is to return either true (keep) or false (ignore) - * - * We use this to potentiallly avoid certain messages (documents): - * - with QueryFlags::SkipUnreadable this will return false for message - * that are not readable in the file-system - * - with QueryFlags::SkipDuplicates this will return false for messages - * whose message-id was seen before. - * - * Even if we do not skip these messages entirely, we remember whether - * they were unreadable/duplicate (in the QueryMatch::Flags), so we can - * quickly find that info when doing the second 'related' query. - * - * The "leader" query. Matches here get the Leader flag unless their - * duplicates / unreadable. We check the duplicate/readable status - * regardless of whether SkipDuplicates/SkipUnreadable was passed - * (to gather that information); however those flags - * affect our true/false verdict. - * - * @param doc xapian document - * - * @return true or false - */ - bool operator() (const Xapian::Document &doc) const override - { - // by definition, we haven't seen the docid before, - // so no need to search - auto it = decider_info_.matches.emplace (doc.get_docid(), make_query_match (doc)); - it.first->second.flags |= QueryMatch::Flags::Leader; + MatchDeciderLeader(QueryFlags qflags, DeciderInfo& info) : MatchDecider(qflags, info) {} + /** + * operator() + * + * This receives the documents considered during a Xapian query, and + * is to return either true (keep) or false (ignore) + * + * We use this to potentiallly avoid certain messages (documents): + * - with QueryFlags::SkipUnreadable this will return false for message + * that are not readable in the file-system + * - with QueryFlags::SkipDuplicates this will return false for messages + * whose message-id was seen before. + * + * Even if we do not skip these messages entirely, we remember whether + * they were unreadable/duplicate (in the QueryMatch::Flags), so we can + * quickly find that info when doing the second 'related' query. + * + * The "leader" query. Matches here get the Leader flag unless their + * duplicates / unreadable. We check the duplicate/readable status + * regardless of whether SkipDuplicates/SkipUnreadable was passed + * (to gather that information); however those flags + * affect our true/false verdict. + * + * @param doc xapian document + * + * @return true or false + */ + bool operator()(const Xapian::Document& doc) const override + { + // by definition, we haven't seen the docid before, + // so no need to search + auto it = decider_info_.matches.emplace(doc.get_docid(), make_query_match(doc)); + it.first->second.flags |= QueryMatch::Flags::Leader; - return should_include (it.first->second); - } + return should_include(it.first->second); + } }; std::unique_ptr -Mu::make_leader_decider (QueryFlags qflags, DeciderInfo &info) +Mu::make_leader_decider(QueryFlags qflags, DeciderInfo& info) { - return std::make_unique (qflags, info); + return std::make_unique(qflags, info); } struct MatchDeciderRelated final : public MatchDecider { - MatchDeciderRelated (QueryFlags qflags, DeciderInfo &info) : MatchDecider (qflags, info) {} - /** - * operator() - * - * This receives the documents considered during a Xapian query, and - * is to return either true (keep) or false (ignore) - * - * We use this to potentially avoid certain messages (documents): - * - with QueryFlags::SkipUnreadable this will return false for message - * that are not readable in the file-system - * - with QueryFlags::SkipDuplicates this will return false for messages - * whose message-id was seen before. - * - * Unlike in the "leader" decider (scroll up), we don't need to remember - * messages we won't include. - * - * @param doc xapian document - * - * @return true or false - */ - bool operator() (const Xapian::Document &doc) const override - { - // we may have seen this match in the "Leader" query. - const auto it = decider_info_.matches.find (doc.get_docid()); - if (it != decider_info_.matches.end()) - return should_include (it->second); + MatchDeciderRelated(QueryFlags qflags, DeciderInfo& info) : MatchDecider(qflags, info) {} + /** + * operator() + * + * This receives the documents considered during a Xapian query, and + * is to return either true (keep) or false (ignore) + * + * We use this to potentially avoid certain messages (documents): + * - with QueryFlags::SkipUnreadable this will return false for message + * that are not readable in the file-system + * - with QueryFlags::SkipDuplicates this will return false for messages + * whose message-id was seen before. + * + * Unlike in the "leader" decider (scroll up), we don't need to remember + * messages we won't include. + * + * @param doc xapian document + * + * @return true or false + */ + bool operator()(const Xapian::Document& doc) const override + { + // we may have seen this match in the "Leader" query. + const auto it = decider_info_.matches.find(doc.get_docid()); + if (it != decider_info_.matches.end()) + return should_include(it->second); - auto qm{make_query_match (doc)}; - if (should_include (qm)) { - qm.flags = QueryMatch::Flags::Related; - decider_info_.matches.emplace (doc.get_docid(), std::move (qm)); - return true; - } else - return false; // nope. - } + auto qm{make_query_match(doc)}; + if (should_include(qm)) { + qm.flags = QueryMatch::Flags::Related; + decider_info_.matches.emplace(doc.get_docid(), std::move(qm)); + return true; + } else + return false; // nope. + } }; std::unique_ptr -Mu::make_related_decider (QueryFlags qflags, DeciderInfo &info) +Mu::make_related_decider(QueryFlags qflags, DeciderInfo& info) { - return std::make_unique (qflags, info); + return std::make_unique(qflags, info); } struct MatchDeciderThread final : public MatchDecider { - MatchDeciderThread (QueryFlags qflags, DeciderInfo &info) : MatchDecider{qflags, info} {} - /** - * operator() - * - * This receives the documents considered during a Xapian query, and - * is to return either true (keep) or false (ignore) - * - * Only include documents that earlier checks have decided to include. - * - * @param doc xapian document - * - * @return true or false - */ - bool operator() (const Xapian::Document &doc) const override - { - // we may have seen this match in the "Leader" query, - // or in the second (unbuounded) related query; - const auto it{decider_info_.matches.find (doc.get_docid())}; - return it != decider_info_.matches.end() && !it->second.thread_path.empty(); - } + MatchDeciderThread(QueryFlags qflags, DeciderInfo& info) : MatchDecider{qflags, info} {} + /** + * operator() + * + * This receives the documents considered during a Xapian query, and + * is to return either true (keep) or false (ignore) + * + * Only include documents that earlier checks have decided to include. + * + * @param doc xapian document + * + * @return true or false + */ + bool operator()(const Xapian::Document& doc) const override + { + // we may have seen this match in the "Leader" query, + // or in the second (unbuounded) related query; + const auto it{decider_info_.matches.find(doc.get_docid())}; + return it != decider_info_.matches.end() && !it->second.thread_path.empty(); + } }; std::unique_ptr -Mu::make_thread_decider (QueryFlags qflags, DeciderInfo &info) +Mu::make_thread_decider(QueryFlags qflags, DeciderInfo& info) { - return std::make_unique (qflags, info); + return std::make_unique(qflags, info); } diff --git a/lib/mu-query-match-deciders.hh b/lib/mu-query-match-deciders.hh index 03cc1663..91488a5e 100644 --- a/lib/mu-query-match-deciders.hh +++ b/lib/mu-query-match-deciders.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_QUERY_MATCH_DECIDERS_HH__ #define MU_QUERY_MATCH_DECIDERS_HH__ @@ -29,30 +28,26 @@ #include "mu-query-results.hh" - namespace Mu { using StringSet = std::unordered_set; - struct DeciderInfo { - QueryMatches matches; - StringSet thread_ids; - StringSet message_ids; + QueryMatches matches; + StringSet thread_ids; + StringSet message_ids; }; /** * Make a "leader" decider, that is, a MatchDecider for either a singular or the * first query in the leader/related pair of queries. Gather information for * threading, and the subsequent "related" query. -* + * * @param qflags query flags * @param match_info receives information about the matches. * * @return a unique_ptr to a match decider. */ -std::unique_ptr make_leader_decider(QueryFlags qflags, - DeciderInfo& info); - +std::unique_ptr make_leader_decider(QueryFlags qflags, DeciderInfo& info); /** * Make a "related" decider, that is, a MatchDecider for the second query @@ -63,9 +58,7 @@ std::unique_ptr make_leader_decider(QueryFlags qflags, * * @return a unique_ptr to a match decider. */ -std::unique_ptr make_related_decider(QueryFlags qflags, - DeciderInfo& info); - +std::unique_ptr make_related_decider(QueryFlags qflags, DeciderInfo& info); /** * Make a "thread" decider, that is, a MatchDecider that removes all but the @@ -76,10 +69,8 @@ std::unique_ptr make_related_decider(QueryFlags qflags, * * @return a unique_ptr to a match decider. */ -std::unique_ptr make_thread_decider (QueryFlags qflags, - DeciderInfo& info); +std::unique_ptr make_thread_decider(QueryFlags qflags, DeciderInfo& info); - -} // namepace Mu +} // namespace Mu #endif /* MU_QUERY_MATCH_DECIDERS_HH__ */ diff --git a/lib/mu-query-matches.hh b/lib/mu-query-matches.hh index 88bc1ac8..052cc791 100644 --- a/lib/mu-query-matches.hh +++ b/lib/mu-query-matches.hh @@ -29,37 +29,29 @@ namespace Mu { - struct QueryMatchInfo { - enum struct Flags { - Seen, - Preferred, - Unreadable, - Duplicate - }; - const std::string message_id; - QueryMatchFlags flags; + enum struct Flags { Seen, Preferred, Unreadable, Duplicate }; + const std::string message_id; + QueryMatchFlags flags; }; MU_ENABLE_BITOPS(QueryMatchInfo::Flags); using MatchInfo = std::unordered_map; struct QueryResults { - enum struct Flags { - None, - Descending, - SkipUnreadable, - SkipDups, - DetermineThreads - }; + enum struct Flags { None, Descending, SkipUnreadable, SkipDups, DetermineThreads }; - QueryResults (const Xapian::MSet& mset, MatchInfo&& match_info, Flags flags): + QueryResults (const Xapian::MSet& mset, MatchInfo&& match_info, Flags flags): mset_{mset}, match_info_(std::Move(match_info), flag_{flags} {} - bool empty() const { return mset_.empty(); } - size_t size() const { return mset_.size(); } + bool empty() const { + return mset_.empty(); } + size_t size() const { + return mset_.size(); } - QueryResultsIterator begin() const { return QueryResultsIterator(mset_.begin()); } - QueryResultsIterator end() const { return QueryResultsIterator(mset_.end()); } + QueryResultsIterator begin() const { + return QueryResultsIterator(mset_.begin()); } + QueryResultsIterator end() const { + return QueryResultsIterator(mset_.end()); } private: const Xapian::MSet mset_; @@ -72,135 +64,148 @@ private: /// unreadable / duplicate messages. /// class QueryResultsIterator { -public: - using iterator_category = std::output_iterator_tag; - using value_type = MuMsg*; - using difference_type = void; - using pointer = void; - using reference = void; + public: + using iterator_category = std::output_iterator_tag; + using value_type = MuMsg*; + using difference_type = void; + using pointer = void; + using reference = void; - QueryResultsIterator(Xapian::MSetIterator it, size_t max_num, - MuMsgFieldId sort_field, MuMsgIterFlags flags, - MatchInfo& minfo): - it_{it}, match_info_{minfo} {} + QueryResultsIterator(Xapian::MSetIterator it, + size_t max_num, + MuMsgFieldId sort_field, + MuMsgIterFlags flags, + MatchInfo& minfo) + : it_{it}, match_info_{minfo} + { + } - QueryResultsIterator& operator++() { return ++it_; return skip();} - QueryResultsIterator& operator++(int) { return it_++; return skip()} + QueryResultsIterator& operator++() + { + return ++it_; + return skip(); + } + QueryResultsIterator& operator++(int) + { + return it_++; + return skip() + } - /** - * Get the Xapian document this iterator is pointing at, - * or an empty document when looking at end(). - * - * @return a document - */ - Xapian::Document document() const() { - g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), {}); - return it_.get_document(); - } + /** + * Get the Xapian document this iterator is pointing at, + * or an empty document when looking at end(). + * + * @return a document + */ + Xapian::Document document() const() + { + g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), {}); + return it_.get_document(); + } - /** - * Get the doc-id for the document this iterator is pointing at, or 0 - * when looking at end. - * - * @return a doc-id. - */ - Xapian::docid doc_id() const { - g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), 0); - return it_.docid(); - } + /** + * Get the doc-id for the document this iterator is pointing at, or 0 + * when looking at end. + * + * @return a doc-id. + */ + Xapian::docid doc_id() const + { + g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), 0); + return it_.docid(); + } - /** - * Get the message-id for the document (message) this iterator is - * pointing at, or "" when looking at end. - * - * @return a message-id - */ - std::string message_id() const { - g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), ""); - return document().get_value(MU_MSG_FIELD_ID_MSGID); - } + /** + * Get the message-id for the document (message) this iterator is + * pointing at, or "" when looking at end. + * + * @return a message-id + */ + std::string message_id() const + { + g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), ""); + return document().get_value(MU_MSG_FIELD_ID_MSGID); + } - /** - * Get the file-system path for the document (message) this iterator is - * pointing at, or "" when looking at end. - * - * @return a filesystem path - */ - std::string path() const { - g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), ""); - return document().get_value(MU_MSG_FIELD_ID_PATH); - } + /** + * Get the file-system path for the document (message) this iterator is + * pointing at, or "" when looking at end. + * + * @return a filesystem path + */ + std::string path() const + { + g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), ""); + return document().get_value(MU_MSG_FIELD_ID_PATH); + } - /** - * Get the references for the document (messages) this is iterator is - * pointing at, or empty if pointing at end of if no references are - * available. - * - * @return references - */ - std::vector references() const { - g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), {}); - return split(document().get_value(MU_MSG_FIELD_ID_REFS), ","); - } + /** + * Get the references for the document (messages) this is iterator is + * pointing at, or empty if pointing at end of if no references are + * available. + * + * @return references + */ + std::vector references() const + { + g_return_val_if_fail(it_ != Xapian::MSetIterator::end(), {}); + return split(document().get_value(MU_MSG_FIELD_ID_REFS), ","); + } -private: - /** - * Filter out some documents - * - * @param forward whether to skip forward when a document is filtered - * out. - * - * @return the first iterator that is not filtered out, or the end - * iterator. - */ - QueryResultsIterator& maybe_skip(bool forward=true) { + private: + /** + * Filter out some documents + * + * @param forward whether to skip forward when a document is filtered + * out. + * + * @return the first iterator that is not filtered out, or the end + * iterator. + */ + QueryResultsIterator& maybe_skip(bool forward = true) + { + if (it_ = MSetIterator::end()) + return *this; // nothing to do. - if (it_ = MSetIterator::end()) - return *this; // nothing to do. - - // Find or create MatchInfo - const auto msgid{message_id()}; - auto mi=[&] { + // Find or create MatchInfo + const auto msgid{message_id()}; + auto mi = [&] { // seen before? auto m{match_info_.find(docid)}; if (m != match_info_.end()) return m; // nope; create. - QueryMatchInfo minfo { message_id() }; + QueryMatchInfo minfo{message_id()}; // not seen before; check. - if (any_of(flags_ & SkipDups) && - match_info_.count(message_id())) + if (any_of(flags_ & SkipDups) && match_info_.count(message_id())) minfo.flags |= Flags::Duplicate; // it's a duplicate - if (any_of(flags_ & SkipUnreadable) && - ::access(path().c_str(), R_OK) != 0) + if (any_of(flags_ & SkipUnreadable) && ::access(path().c_str(), R_OK) != 0) minfo.flags |= Flags::Unreadable; return match_info_.emplace_back(std::move(minfo)); - }(); + }(); - // note: SkipDups / SkipUnreadable are not set if - // if we're not checking for those. + // note: SkipDups / SkipUnreadable are not set if + // if we're not checking for those. - if (any_of(mi->second.flags_ & SkipDups) || - any_of(mi->second.flags_ & SkipUnreadable)) { - if (forward) - ++it_; - else - --it_; + if (any_of(mi->second.flags_ & SkipDups) || + any_of(mi->second.flags_ & SkipUnreadable)) { + if (forward) + ++it_; + else + --it_; - return maybe_skip(); - } + return maybe_skip(); + } - return *this; - } + return *this; + } - Xapian::MSetIterator it_; - MatchInfo& match_info_; + Xapian::MSetIterator it_; + MatchInfo& match_info_; }; - }; // namespace Mu - #endif /* MU_QUERY_MATCHES_HH__ */ diff --git a/lib/mu-query-results.hh b/lib/mu-query-results.hh index 1cc157c5..7302e652 100644 --- a/lib/mu-query-results.hh +++ b/lib/mu-query-results.hh @@ -39,8 +39,7 @@ #include "mu-msg.hh" -namespace Mu -{ +namespace Mu { /** * This implements a QueryResults structure, which capture the results of a @@ -51,103 +50,103 @@ namespace Mu /// Flags that influence now matches are presented (or skipped) enum struct QueryFlags { - None = 0, /**< no flags */ - Descending = 1 << 0, /**< sort z->a */ - SkipUnreadable = 1 << 1, /**< skip unreadable msgs */ - SkipDuplicates = 1 << 2, /**< skip duplicate msgs */ - IncludeRelated = 1 << 3, /**< include related msgs */ - Threading = 1 << 4, /**< calculate threading info */ - // internal - Leader = 1 << 5, /**< This is the leader query (for internal use - * only)*/ + None = 0, /**< no flags */ + Descending = 1 << 0, /**< sort z->a */ + SkipUnreadable = 1 << 1, /**< skip unreadable msgs */ + SkipDuplicates = 1 << 2, /**< skip duplicate msgs */ + IncludeRelated = 1 << 3, /**< include related msgs */ + Threading = 1 << 4, /**< calculate threading info */ + // internal + Leader = 1 << 5, /**< This is the leader query (for internal use + * only)*/ }; -MU_ENABLE_BITOPS (QueryFlags); +MU_ENABLE_BITOPS(QueryFlags); /// Stores all the essential information for sorting the results. struct QueryMatch { - /// Flags for a match (message) found - enum struct Flags { - None = 0, /**< No Flags */ - Leader = 1 << 0, /**< Mark direct matches as leader */ - Related = 1 << 1, /**< A related message */ - Unreadable = 1 << 2, /**< No readable file */ - Duplicate = 1 << 3, /**< Message-id seen before */ + /// Flags for a match (message) found + enum struct Flags { + None = 0, /**< No Flags */ + Leader = 1 << 0, /**< Mark direct matches as leader */ + Related = 1 << 1, /**< A related message */ + Unreadable = 1 << 2, /**< No readable file */ + Duplicate = 1 << 3, /**< Message-id seen before */ - Root = 1 << 10, /**< Is this the thread-root? */ - First = 1 << 11, /**< Is this the first message in a thread? */ - Last = 1 << 12, /**< Is this the last message in a thread? */ - Orphan = 1 << 13, /**< Is this message without a parent? */ - HasChild = 1 << 14, /**< Does this message have a child? */ + Root = 1 << 10, /**< Is this the thread-root? */ + First = 1 << 11, /**< Is this the first message in a thread? */ + Last = 1 << 12, /**< Is this the last message in a thread? */ + Orphan = 1 << 13, /**< Is this message without a parent? */ + HasChild = 1 << 14, /**< Does this message have a child? */ - ThreadSubject = 1 << 20, /**< Message holds subject for (sub)thread */ - }; + ThreadSubject = 1 << 20, /**< Message holds subject for (sub)thread */ + }; - Flags flags{Flags::None}; /**< Flags */ - std::string date_key; /**< The date-key (for sorting all sub-root levels) */ - // the thread subject is the subject of the first message in a thread, - // and any message that has a different subject compared to its predecessor - // (ignoring prefixes such as Re:) - // - // otherwise, it is empty. - std::string subject; /**< subject for this message */ - size_t thread_level{}; /**< The thread level */ - std::string thread_path; /**< The hex-numerial path in the thread, ie. '00:01:0a' */ - std::string thread_date; /**< date of newest message in thread */ + Flags flags{Flags::None}; /**< Flags */ + std::string date_key; /**< The date-key (for sorting all sub-root levels) */ + // the thread subject is the subject of the first message in a thread, + // and any message that has a different subject compared to its predecessor + // (ignoring prefixes such as Re:) + // + // otherwise, it is empty. + std::string subject; /**< subject for this message */ + size_t thread_level{}; /**< The thread level */ + std::string thread_path; /**< The hex-numerial path in the thread, ie. '00:01:0a' */ + std::string thread_date; /**< date of newest message in thread */ - bool operator< (const QueryMatch &rhs) const { return date_key < rhs.date_key; } + bool operator<(const QueryMatch& rhs) const { return date_key < rhs.date_key; } - bool has_flag (Flags flag) const; + bool has_flag(Flags flag) const; }; -MU_ENABLE_BITOPS (QueryMatch::Flags); +MU_ENABLE_BITOPS(QueryMatch::Flags); inline bool -QueryMatch::has_flag (QueryMatch::Flags flag) const +QueryMatch::has_flag(QueryMatch::Flags flag) const { - return any_of (flags & flag); + return any_of(flags & flag); } -inline std::ostream & -operator<< (std::ostream &os, QueryMatch::Flags mflags) +inline std::ostream& +operator<<(std::ostream& os, QueryMatch::Flags mflags) { - if (mflags == QueryMatch::Flags::None) { - os << ""; - return os; - } + if (mflags == QueryMatch::Flags::None) { + os << ""; + return os; + } - if (any_of (mflags & QueryMatch::Flags::Leader)) - os << "leader "; - if (any_of (mflags & QueryMatch::Flags::Unreadable)) - os << "unreadable "; - if (any_of (mflags & QueryMatch::Flags::Duplicate)) - os << "dup "; + if (any_of(mflags & QueryMatch::Flags::Leader)) + os << "leader "; + if (any_of(mflags & QueryMatch::Flags::Unreadable)) + os << "unreadable "; + if (any_of(mflags & QueryMatch::Flags::Duplicate)) + os << "dup "; - if (any_of (mflags & QueryMatch::Flags::Root)) - os << "root "; - if (any_of (mflags & QueryMatch::Flags::Related)) - os << "related "; - if (any_of (mflags & QueryMatch::Flags::First)) - os << "first "; - if (any_of (mflags & QueryMatch::Flags::Last)) - os << "last "; - if (any_of (mflags & QueryMatch::Flags::Orphan)) - os << "orphan "; - if (any_of (mflags & QueryMatch::Flags::HasChild)) - os << "has-child "; + if (any_of(mflags & QueryMatch::Flags::Root)) + os << "root "; + if (any_of(mflags & QueryMatch::Flags::Related)) + os << "related "; + if (any_of(mflags & QueryMatch::Flags::First)) + os << "first "; + if (any_of(mflags & QueryMatch::Flags::Last)) + os << "last "; + if (any_of(mflags & QueryMatch::Flags::Orphan)) + os << "orphan "; + if (any_of(mflags & QueryMatch::Flags::HasChild)) + os << "has-child "; - return os; + return os; } using QueryMatches = std::unordered_map; -inline std::ostream & -operator<< (std::ostream &os, const QueryMatch &qmatch) +inline std::ostream& +operator<<(std::ostream& os, const QueryMatch& qmatch) { - os << "qm:[" << qmatch.thread_path << "]: " // " (" << qmatch.thread_level << "): " - << "> date:<" << qmatch.date_key << "> " - << "flags:{" << qmatch.flags << "}"; + os << "qm:[" << qmatch.thread_path << "]: " // " (" << qmatch.thread_level << "): " + << "> date:<" << qmatch.date_key << "> " + << "flags:{" << qmatch.flags << "}"; - return os; + return os; } /// @@ -157,246 +156,244 @@ operator<< (std::ostream &os, const QueryMatch &qmatch) /// Note, we internally skip unreadable/duplicate messages (when asked too); those /// skipped ones do _not_ count towards the max_size /// -class QueryResultsIterator -{ - public: - using iterator_category = std::output_iterator_tag; - using value_type = MuMsg *; - using difference_type = void; - using pointer = void; - using reference = void; +class QueryResultsIterator { + public: + using iterator_category = std::output_iterator_tag; + using value_type = MuMsg*; + using difference_type = void; + using pointer = void; + using reference = void; - QueryResultsIterator (Xapian::MSetIterator mset_it, QueryMatches &query_matches) - : mset_it_{mset_it}, query_matches_{query_matches} - { - } - ~QueryResultsIterator() { g_clear_pointer (&msg_, mu_msg_unref); } + QueryResultsIterator(Xapian::MSetIterator mset_it, QueryMatches& query_matches) + : mset_it_{mset_it}, query_matches_{query_matches} + { + } + ~QueryResultsIterator() { g_clear_pointer(&msg_, mu_msg_unref); } - /** - * Increment the iterator (we don't support post-increment) - * - * @return an updated iterator, or end() if we were already at end() - */ - QueryResultsIterator &operator++() - { - ++mset_it_; - return *this; - } + /** + * Increment the iterator (we don't support post-increment) + * + * @return an updated iterator, or end() if we were already at end() + */ + QueryResultsIterator& operator++() + { + ++mset_it_; + return *this; + } - /** - * (Non)Equivalence operators - * - * @param rhs some other iterator - * - * @return true or false - */ - bool operator== (const QueryResultsIterator &rhs) const { return mset_it_ == rhs.mset_it_; } - bool operator!= (const QueryResultsIterator &rhs) const { return mset_it_ != rhs.mset_it_; } + /** + * (Non)Equivalence operators + * + * @param rhs some other iterator + * + * @return true or false + */ + bool operator==(const QueryResultsIterator& rhs) const { return mset_it_ == rhs.mset_it_; } + bool operator!=(const QueryResultsIterator& rhs) const { return mset_it_ != rhs.mset_it_; } - QueryResultsIterator & operator*() { return *this; } - const QueryResultsIterator &operator*() const { return *this; } + QueryResultsIterator& operator*() { return *this; } + const QueryResultsIterator& operator*() const { return *this; } - /** - * Get the Xapian document this iterator is pointing at, - * or an empty document when looking at end(). - * - * @return a document - */ - Xapian::Document document() const { return mset_it_.get_document(); } + /** + * Get the Xapian document this iterator is pointing at, + * or an empty document when looking at end(). + * + * @return a document + */ + Xapian::Document document() const { return mset_it_.get_document(); } - /** - * Get the doc-id for the document this iterator is pointing at, or 0 - * when looking at end. - * - * @return a doc-id. - */ - Xapian::docid doc_id() const { return *mset_it_; } + /** + * Get the doc-id for the document this iterator is pointing at, or 0 + * when looking at end. + * + * @return a doc-id. + */ + Xapian::docid doc_id() const { return *mset_it_; } - /** - * Get the message-id for the document (message) this iterator is - * pointing at, or not when not available - * - * @return a message-id - */ - Option message_id() const noexcept - { - return opt_string (MU_MSG_FIELD_ID_MSGID); - } + /** + * Get the message-id for the document (message) this iterator is + * pointing at, or not when not available + * + * @return a message-id + */ + Option message_id() const noexcept + { + return opt_string(MU_MSG_FIELD_ID_MSGID); + } - /** - * Get the thread-id for the document (message) this iterator is - * pointing at, or Nothing. - * - * @return a message-id - */ - Option thread_id() const noexcept - { - return opt_string (MU_MSG_FIELD_ID_THREAD_ID); - } + /** + * Get the thread-id for the document (message) this iterator is + * pointing at, or Nothing. + * + * @return a message-id + */ + Option thread_id() const noexcept + { + return opt_string(MU_MSG_FIELD_ID_THREAD_ID); + } - /** - * Get the file-system path for the document (message) this iterator is - * pointing at, or Nothing. - * - * @return a filesystem path - */ - Option path() const noexcept { return opt_string (MU_MSG_FIELD_ID_PATH); } + /** + * Get the file-system path for the document (message) this iterator is + * pointing at, or Nothing. + * + * @return a filesystem path + */ + Option path() const noexcept { return opt_string(MU_MSG_FIELD_ID_PATH); } - /** - * Get the date for the document (message) the iterator is pointing at. - * pointing at, or Nothing. - * - * @return a filesystem path - */ - Option date() const noexcept { return opt_string (MU_MSG_FIELD_ID_DATE); } + /** + * Get the date for the document (message) the iterator is pointing at. + * pointing at, or Nothing. + * + * @return a filesystem path + */ + Option date() const noexcept { return opt_string(MU_MSG_FIELD_ID_DATE); } - /** - * Get the file-system path for the document (message) this iterator is - * pointing at. - * - * @return the subject - */ - Option subject() const noexcept - { - return opt_string (MU_MSG_FIELD_ID_SUBJECT); - } + /** + * Get the file-system path for the document (message) this iterator is + * pointing at. + * + * @return the subject + */ + Option subject() const noexcept { return opt_string(MU_MSG_FIELD_ID_SUBJECT); } - /** - * Get the references for the document (messages) this is iterator is - * pointing at, or empty if pointing at end of if no references are - * available. - * - * @return references - */ - std::vector references() const noexcept - { - return split (document().get_value (MU_MSG_FIELD_ID_REFS), ","); - } + /** + * Get the references for the document (messages) this is iterator is + * pointing at, or empty if pointing at end of if no references are + * available. + * + * @return references + */ + std::vector references() const noexcept + { + return split(document().get_value(MU_MSG_FIELD_ID_REFS), ","); + } - /** - * Get some value from the document, or Nothing if empty. - * - * @param id a message field id - * - * @return the value - */ - Option opt_string (MuMsgFieldId id) const noexcept - try { - auto &&val{document().get_value (id)}; - return val.empty() ? Nothing : Some (val); - } - MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing); + /** + * Get some value from the document, or Nothing if empty. + * + * @param id a message field id + * + * @return the value + */ + Option opt_string(MuMsgFieldId id) const noexcept + { + std::string empty; + std::string val = xapian_try([&] { return document().get_value(id); }, empty); + if (val.empty()) + return Nothing; + else + return Some(std::move(val)); + } - /** - * Get the Query match info for this message. - * - * @return the match info. - */ - QueryMatch &query_match() - { - g_assert (query_matches_.find (document().get_docid()) != query_matches_.end()); - return query_matches_.find (document().get_docid())->second; - } - const QueryMatch &query_match() const - { - g_assert (query_matches_.find (document().get_docid()) != query_matches_.end()); - return query_matches_.find (document().get_docid())->second; - } + /** + * Get the Query match info for this message. + * + * @return the match info. + */ + QueryMatch& query_match() + { + g_assert(query_matches_.find(document().get_docid()) != query_matches_.end()); + return query_matches_.find(document().get_docid())->second; + } + const QueryMatch& query_match() const + { + g_assert(query_matches_.find(document().get_docid()) != query_matches_.end()); + return query_matches_.find(document().get_docid())->second; + } - /** - * get the corresponding MuMsg for this iter; this instance is owned by - * @this, and becomes invalid when iterating to the next, or @this is -k * destroyed.; it's a 'floating' reference. - * - * @return a MuMsg* or NUL in case of error - */ - MuMsg *floating_msg() G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT - try { - auto docp{reinterpret_cast (new Xapian::Document (document()))}; - GError *err{}; - g_clear_pointer (&msg_, mu_msg_unref); - if (!(msg_ = mu_msg_new_from_doc (docp, &err))) { - delete docp; - g_warning ("failed to crate message for %s: %s", - path().value_or ("").c_str(), - err ? err->message : "somethng went wrong"); - g_clear_error (&err); - } + /** + * get the corresponding MuMsg for this iter; this instance is owned by + * @this, and becomes invalid when iterating to the next, or @this is + * destroyed.; it's a 'floating' reference. + * + * @return a MuMsg* or NUL in case of error + */ + MuMsg* floating_msg() G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT + { + return xapian_try( + [&] { + auto docp{reinterpret_cast( + new Xapian::Document(document()))}; + GError* err{}; + g_clear_pointer(&msg_, mu_msg_unref); + if (!(msg_ = mu_msg_new_from_doc(docp, &err))) { + delete docp; + g_warning("failed to crate message for %s: %s", + path().value_or("").c_str(), + err ? err->message : "somethng went wrong"); + g_clear_error(&err); + } + return msg_; + }, + (MuMsg*)NULL); + } - return msg_; - } - MU_XAPIAN_CATCH_BLOCK_RETURN (NULL); - - private: - Xapian::MSetIterator mset_it_; - QueryMatches & query_matches_; - MuMsg * msg_{}; + private: + Xapian::MSetIterator mset_it_; + QueryMatches& query_matches_; + MuMsg* msg_{}; }; constexpr auto MaxQueryResultsSize = std::numeric_limits::max(); -class QueryResults -{ - public: - /// Helper types - using iterator = QueryResultsIterator; - using const_iterator = const iterator; +class QueryResults { + public: + /// Helper types + using iterator = QueryResultsIterator; + using const_iterator = const iterator; - /** - * Construct a QueryResults object - * - * @param mset an Xapian::MSet with matches - */ - QueryResults (const Xapian::MSet &mset, QueryMatches &&query_matches) - : mset_{mset}, query_matches_{std::move (query_matches)} - { - } - /** - * Is this QueryResults object empty (ie., no matches)? - * - * @return true are false - */ - bool empty() const { return mset_.empty(); } + /** + * Construct a QueryResults object + * + * @param mset an Xapian::MSet with matches + */ + QueryResults(const Xapian::MSet& mset, QueryMatches&& query_matches) + : mset_{mset}, query_matches_{std::move(query_matches)} + { + } + /** + * Is this QueryResults object empty (ie., no matches)? + * + * @return true are false + */ + bool empty() const { return mset_.empty(); } - /** - * Get the number of matches in this QueryResult - * - * @return number of matches - */ - size_t size() const { return mset_.size(); } + /** + * Get the number of matches in this QueryResult + * + * @return number of matches + */ + size_t size() const { return mset_.size(); } - /** - * Get the begin iterator to the results. - * - * @return iterator - */ - iterator begin() { return QueryResultsIterator (mset_.begin(), query_matches_); } - const iterator begin() const - { - return QueryResultsIterator (mset_.begin(), query_matches_); - } + /** + * Get the begin iterator to the results. + * + * @return iterator + */ + iterator begin() { return QueryResultsIterator(mset_.begin(), query_matches_); } + const iterator begin() const { return QueryResultsIterator(mset_.begin(), query_matches_); } - /** - * Get the end iterator to the results. - * - * @return iterator - */ - iterator end() { return QueryResultsIterator (mset_.end(), query_matches_); } - const_iterator end() const { return QueryResultsIterator (mset_.end(), query_matches_); } + /** + * Get the end iterator to the results. + * + * @return iterator + */ + iterator end() { return QueryResultsIterator(mset_.end(), query_matches_); } + const_iterator end() const { return QueryResultsIterator(mset_.end(), query_matches_); } - /** - * Get the query-matches for these QueryResults. The non-const - * version can be use to _steal_ the query results, by moving - * them. - * - * @return query-matches - */ - const QueryMatches &query_matches() const { return query_matches_; } - QueryMatches & query_matches() { return query_matches_; } + /** + * Get the query-matches for these QueryResults. The non-const + * version can be use to _steal_ the query results, by moving + * them. + * + * @return query-matches + */ + const QueryMatches& query_matches() const { return query_matches_; } + QueryMatches& query_matches() { return query_matches_; } - private: - const Xapian::MSet mset_; - mutable QueryMatches query_matches_; + private: + const Xapian::MSet mset_; + mutable QueryMatches query_matches_; }; } // namespace Mu diff --git a/lib/mu-query-threads.cc b/lib/mu-query-threads.cc index 545d0b96..30710905 100644 --- a/lib/mu-query-threads.cc +++ b/lib/mu-query-threads.cc @@ -28,76 +28,80 @@ #include #include - #include using namespace Mu; struct Container { - using Containers = std::vector; + using Containers = std::vector; - Container() = default; - Container(Option msg): query_match{msg} {} - Container(const Container&) = delete; - Container(Container&&) = default; + Container() = default; + Container(Option msg) : query_match{msg} {} + Container(const Container&) = delete; + Container(Container&&) = default; - void add_child (Container& new_child) { - new_child.parent = this; - children.emplace_back(&new_child); - } - void remove_child (Container& child) { - children.erase(find_child(child)); - assert(!has_child(child)); - } + void add_child(Container& new_child) + { + new_child.parent = this; + children.emplace_back(&new_child); + } + void remove_child(Container& child) + { + children.erase(find_child(child)); + assert(!has_child(child)); + } - Containers::iterator find_child (Container& child) { - return std::find_if(children.begin(), children.end(), - [&](auto&& c){ return c == &child; }); - } - Containers::const_iterator find_child (Container& child) const { - return std::find_if(children.begin(), children.end(), - [&](auto&& c){ return c == &child; }); - } - bool has_child (Container& child) const { - return find_child(child) != children.cend(); - } + Containers::iterator find_child(Container& child) + { + return std::find_if(children.begin(), children.end(), [&](auto&& c) { + return c == &child; + }); + } + Containers::const_iterator find_child(Container& child) const + { + return std::find_if(children.begin(), children.end(), [&](auto&& c) { + return c == &child; + }); + } + bool has_child(Container& child) const { return find_child(child) != children.cend(); } - bool is_reachable(Container* other) const { - auto up{ur_parent()}; - return up && up == other->ur_parent(); - } - template void for_each_child (Func&& func) { - auto it{children.rbegin()}; - while (it != children.rend()) { - auto next = std::next(it); - func(*it); - it = next; - } - } - // During sorting, this is the cached value for the (recursive) date-key - // of this container -- ie.. either the one from the first of its - // children, or from its query-match, if it has no children. - // - // Note that the sub-root-levels of threads are always sorted by date, - // in ascending order, regardless of whatever sorting was specified for - // the root-level. + bool is_reachable(Container* other) const + { + auto up{ur_parent()}; + return up && up == other->ur_parent(); + } + template void for_each_child(Func&& func) + { + auto it{children.rbegin()}; + while (it != children.rend()) { + auto next = std::next(it); + func(*it); + it = next; + } + } + // During sorting, this is the cached value for the (recursive) date-key + // of this container -- ie.. either the one from the first of its + // children, or from its query-match, if it has no children. + // + // Note that the sub-root-levels of threads are always sorted by date, + // in ascending order, regardless of whatever sorting was specified for + // the root-level. + std::string thread_date_key; - std::string thread_date_key; + Option query_match; + bool is_nuked{}; + Container* parent{}; + Containers children; + using ContainerVec = std::vector; - Option query_match; - bool is_nuked{}; - Container* parent{}; - Containers children; - - using ContainerVec = std::vector; - -private: - const Container* ur_parent() const { - assert(this->parent != this); - return parent ? parent->ur_parent() : this; - } + private: + const Container* ur_parent() const + { + assert(this->parent != this); + return parent ? parent->ur_parent() : this; + } }; using Containers = Container::Containers; @@ -106,138 +110,138 @@ using ContainerVec = Container::ContainerVec; static std::ostream& operator<<(std::ostream& os, const Container& container) { - os << "container: " << std::right << std::setw(10) << &container - << ": parent: " << std::right << std::setw(10) << container.parent - << " [" << container.thread_date_key << "]" - << "\n children: "; + os << "container: " << std::right << std::setw(10) << &container + << ": parent: " << std::right << std::setw(10) << container.parent << " [" + << container.thread_date_key << "]" + << "\n children: "; - for (auto&& c: container.children) - os << std::right << std::setw(10) << c << " "; + for (auto&& c : container.children) + os << std::right << std::setw(10) << c << " "; - os << (container.is_nuked ? " nuked" : ""); + os << (container.is_nuked ? " nuked" : ""); - if (container.query_match) - os << "\n " << container.query_match.value(); + if (container.query_match) + os << "\n " << container.query_match.value(); - return os; + return os; } - -using IdTable = std::unordered_map; +using IdTable = std::unordered_map; using DupTable = std::multimap; static void -handle_duplicates (IdTable& id_table, DupTable& dup_table) +handle_duplicates(IdTable& id_table, DupTable& dup_table) { - size_t n{}; + size_t n{}; - for (auto&& dup: dup_table) { - const auto msgid{dup.first}; - auto it = id_table.find(msgid); - if (it == id_table.end()) - continue; + for (auto&& dup : dup_table) { + const auto msgid{dup.first}; + auto it = id_table.find(msgid); + if (it == id_table.end()) + continue; - // add duplicates as fake children - char buf[32]; - ::snprintf(buf, sizeof(buf), "dup-%zu", ++n); - it->second.add_child( - id_table.emplace(buf, std::move(dup.second)).first->second); - } + // add duplicates as fake children + char buf[32]; + ::snprintf(buf, sizeof(buf), "dup-%zu", ++n); + it->second.add_child(id_table.emplace(buf, std::move(dup.second)).first->second); + } } template static IdTable -determine_id_table (QueryResultsType& qres) +determine_id_table(QueryResultsType& qres) { - // 1. For each query_match - IdTable id_table; - DupTable dups; - for (auto&& mi: qres) { - const auto msgid{mi.message_id().value_or(*mi.path())}; - // Step 0 (non-JWZ): filter out dups, handle those at the end - if (mi.query_match().has_flag(QueryMatch::Flags::Duplicate)) { - dups.emplace(msgid, mi.query_match()); - continue; - } - // 1.A If id_table contains an empty Container for this ID: - // Store this query_match (query_match) in the Container's query_match (value) slot. - // Else: - // Create a new Container object holding this query_match (query-match); - // Index the Container by Query_Match-ID - auto c_it = id_table.find(msgid); - auto& container = [&]()->Container& { - if (c_it != id_table.end()) { - if (!c_it->second.query_match) // hmm, dup? - c_it->second.query_match = mi.query_match(); - return c_it->second; - } else { - // Else: - // Create a new Container object holding this query_match (query-match); - // Index the Container by Query_Match-ID - return id_table.emplace(msgid, mi.query_match()).first->second; - } - }(); + // 1. For each query_match + IdTable id_table; + DupTable dups; + for (auto&& mi : qres) { + const auto msgid{mi.message_id().value_or(*mi.path())}; + // Step 0 (non-JWZ): filter out dups, handle those at the end + if (mi.query_match().has_flag(QueryMatch::Flags::Duplicate)) { + dups.emplace(msgid, mi.query_match()); + continue; + } + // 1.A If id_table contains an empty Container for this ID: + // Store this query_match (query_match) in the Container's query_match (value) slot. + // Else: + // Create a new Container object holding this query_match (query-match); + // Index the Container by Query_Match-ID + auto c_it = id_table.find(msgid); + auto& container = [&]() -> Container& { + if (c_it != id_table.end()) { + if (!c_it->second.query_match) // hmm, dup? + c_it->second.query_match = mi.query_match(); + return c_it->second; + } else { + // Else: + // Create a new Container object holding this query_match + // (query-match); Index the Container by Query_Match-ID + return id_table.emplace(msgid, mi.query_match()).first->second; + } + }(); - // We sort by date (ascending), *except* for the root; we don't - // know what query_matchs will be at the root level yet, so remember - // both. Moreover, even when sorting the top-level in descending - // order, still sort the thread levels below that in ascending - // order. - container.thread_date_key = container.query_match->date_key = - mi.date().value_or(""); - // initial guess for the thread-date; might be updated - // later. + // We sort by date (ascending), *except* for the root; we don't + // know what query_matchs will be at the root level yet, so remember + // both. Moreover, even when sorting the top-level in descending + // order, still sort the thread levels below that in ascending + // order. + container.thread_date_key = container.query_match->date_key = + mi.date().value_or(""); + // initial guess for the thread-date; might be updated + // later. - // remember the subject, we use it to determine the (sub)thread subject - container.query_match->subject = mi.subject().value_or(""); + // remember the subject, we use it to determine the (sub)thread subject + container.query_match->subject = mi.subject().value_or(""); - // 1.B - // For each element in the query_match's References field: - Container* parent_ref_container{}; - for (const auto& ref: mi.references()) { - // grand_-parent -> grand_-parent -> ... -> parent. + // 1.B + // For each element in the query_match's References field: + Container* parent_ref_container{}; + for (const auto& ref : mi.references()) { + // grand_-parent -> grand_-parent -> ... -> parent. - // Find a Container object for the given Query_Match-ID; If it exists, use it; - // otherwise make one with a null Query_Match. - auto ref_container = [&]()->Container* { - auto ref_it = id_table.find(ref); - if (ref_it == id_table.end()) - ref_it = id_table.emplace(ref,Nothing).first; - return &ref_it->second; - }(); + // Find a Container object for the given Query_Match-ID; If it exists, use + // it; otherwise make one with a null Query_Match. + auto ref_container = [&]() -> Container* { + auto ref_it = id_table.find(ref); + if (ref_it == id_table.end()) + ref_it = id_table.emplace(ref, Nothing).first; + return &ref_it->second; + }(); - // Link the References field's Containers together in the order implied - // by the References header. - // * If they are already linked, don't change the existing links. - // - // * Do not add a link if adding that link would introduce a loop: that is, - // before asserting A->B, search down the children of B to see if A is - // reachable, and also search down the children of A to see if B is - // reachable. If either is already reachable as a child of the other, - // don't add the link. - if (parent_ref_container && !ref_container->parent) { - if (!parent_ref_container->is_reachable(ref_container)) - parent_ref_container->add_child(*ref_container); - // else - // g_message ("%u: reachable %s -> %s", __LINE__, msgid.c_str(), ref.c_str()); - } + // Link the References field's Containers together in the order implied + // by the References header. + // * If they are already linked, don't change the existing links. + // + // * Do not add a link if adding that link would introduce a loop: that is, + // before asserting A->B, search down the children of B to see if A is + // reachable, and also search down the children of A to see if B is + // reachable. If either is already reachable as a child of the other, + // don't add the link. + if (parent_ref_container && !ref_container->parent) { + if (!parent_ref_container->is_reachable(ref_container)) + parent_ref_container->add_child(*ref_container); + // else + // g_message ("%u: reachable %s -> %s", __LINE__, + // msgid.c_str(), ref.c_str()); + } - parent_ref_container = ref_container; - } + parent_ref_container = ref_container; + } - // Add the query_match to the chain. - if (parent_ref_container && !container.parent) { - if (!parent_ref_container->is_reachable(&container)) - parent_ref_container->add_child(container); - // else - // g_message ("%u: reachable %s -> parent", __LINE__, msgid.c_str()); - } - } + // Add the query_match to the chain. + if (parent_ref_container && !container.parent) { + if (!parent_ref_container->is_reachable(&container)) + parent_ref_container->add_child(container); + // else + // g_message ("%u: reachable %s -> parent", __LINE__, + // msgid.c_str()); + } + } - // non-JWZ: add duplicate messages. - handle_duplicates (id_table, dups); + // non-JWZ: add duplicate messages. + handle_duplicates(id_table, dups); - return id_table; + return id_table; } /// Recursively walk all containers under the root set. @@ -278,98 +282,94 @@ determine_id_table (QueryResultsType& qres) /// set -- unless there is only one child, in which case, do. static void -prune (Container* child) +prune(Container* child) { - Container *container{child->parent}; + Container* container{child->parent}; - for (auto& grandchild: child->children) { - grandchild->parent = container; - if (container) - container->children.emplace_back(grandchild); - } + for (auto& grandchild : child->children) { + grandchild->parent = container; + if (container) + container->children.emplace_back(grandchild); + } - child->children.clear(); - child->is_nuked = true; + child->children.clear(); + child->is_nuked = true; - if (container) - container->remove_child(*child); + if (container) + container->remove_child(*child); } - static bool -prune_empty_containers (Container& container) +prune_empty_containers(Container& container) { - Containers to_prune; + Containers to_prune; - container.for_each_child([&](auto& child){ - if (prune_empty_containers(*child)) - to_prune.emplace_back(child); - }); + container.for_each_child([&](auto& child) { + if (prune_empty_containers(*child)) + to_prune.emplace_back(child); + }); - for (auto& child: to_prune) - prune (child); + for (auto& child : to_prune) + prune(child); - // Never nuke these. - if (container.query_match) - return false; + // Never nuke these. + if (container.query_match) + return false; - // If it is an empty container with no children, nuke it. - // - // If the Container is empty, but does have children, remove this - // container but promote its children to this level (that is, splice them in - // to the current child list.) - // - // Do not promote the children if doing so would promote them to the root - // set -- unless there is only one child, in which case, do. - //const auto rootset_child{!container.parent->parent}; - if (container.parent || container.children.size() <= 1) - return true; // splice/nuke it. + // If it is an empty container with no children, nuke it. + // + // If the Container is empty, but does have children, remove this + // container but promote its children to this level (that is, splice them in + // to the current child list.) + // + // Do not promote the children if doing so would promote them to the root + // set -- unless there is only one child, in which case, do. + // const auto rootset_child{!container.parent->parent}; + if (container.parent || container.children.size() <= 1) + return true; // splice/nuke it. - return false; + return false; } - static void -prune_empty_containers (IdTable& id_table) +prune_empty_containers(IdTable& id_table) { - for (auto&& item: id_table) { + for (auto&& item : id_table) { + auto& child(item.second); + if (child.parent) + continue; // not a root child. - auto& child(item.second); - if (child.parent) - continue; // not a root child. - - if (prune_empty_containers(item.second)) - prune(&child); - } + if (prune_empty_containers(item.second)) + prune(&child); + } } // // Sorting. // - /// Register some information about a match (i.e., message) that we can use for /// subsequent queries. using ThreadPath = std::vector; inline std::string -to_string (const ThreadPath& tpath, size_t digits) +to_string(const ThreadPath& tpath, size_t digits) { - std::string str; - str.reserve(tpath.size() * digits); + std::string str; + str.reserve(tpath.size() * digits); - bool first{true}; - for (auto&& segm: tpath) { - str += format("%s%0*x", first ? "" : ":", (int)digits, segm); - first = false; - } + bool first{true}; + for (auto&& segm : tpath) { + str += format("%s%0*x", first ? "" : ":", (int)digits, segm); + first = false; + } - return str; + return str; } static bool // compare subjects, ignore anything before the last ':*' -subject_matches (const std::string& sub1, const std::string& sub2) +subject_matches(const std::string& sub1, const std::string& sub2) { - auto search_str =[](const std::string&s) -> const char* { + auto search_str = [](const std::string& s) -> const char* { const auto pos = s.find_last_of(':'); if (pos == std::string::npos) return s.c_str(); @@ -379,562 +379,541 @@ subject_matches (const std::string& sub1, const std::string& sub2) } }; - //g_debug ("'%s' '%s'", search_str(sub1), search_str(sub2)); + // g_debug ("'%s' '%s'", search_str(sub1), search_str(sub2)); return g_strcmp0(search_str(sub1), search_str(sub2)) == 0; } static bool -update_container (Container& container, bool descending, - ThreadPath& tpath, size_t seg_size, - const std::string& prev_subject="") +update_container(Container& container, + bool descending, + ThreadPath& tpath, + size_t seg_size, + const std::string& prev_subject = "") { - if (!container.children.empty()) { - Container* first = container.children.front(); - if (first->query_match) - first->query_match->flags |= QueryMatch::Flags::First; - Container* last = container.children.back(); - if (last->query_match) - last->query_match->flags |= QueryMatch::Flags::Last; - } + if (!container.children.empty()) { + Container* first = container.children.front(); + if (first->query_match) + first->query_match->flags |= QueryMatch::Flags::First; + Container* last = container.children.back(); + if (last->query_match) + last->query_match->flags |= QueryMatch::Flags::Last; + } - if (!container.query_match) - return false; // nothing else to do. + if (!container.query_match) + return false; // nothing else to do. - auto& qmatch(*container.query_match); - if (!container.parent) - qmatch.flags |= QueryMatch::Flags::Root; - else if (!container.parent->query_match) - qmatch.flags |= QueryMatch::Flags::Orphan; + auto& qmatch(*container.query_match); + if (!container.parent) + qmatch.flags |= QueryMatch::Flags::Root; + else if (!container.parent->query_match) + qmatch.flags |= QueryMatch::Flags::Orphan; - if (!container.children.empty()) - qmatch.flags |= QueryMatch::Flags::HasChild; + if (!container.children.empty()) + qmatch.flags |= QueryMatch::Flags::HasChild; - if (qmatch.has_flag(QueryMatch::Flags::Root) || prev_subject.empty() || + if (qmatch.has_flag(QueryMatch::Flags::Root) || prev_subject.empty() || !subject_matches(prev_subject, qmatch.subject)) - qmatch.flags |= QueryMatch::Flags::ThreadSubject; + qmatch.flags |= QueryMatch::Flags::ThreadSubject; - if (descending && container.parent) { - // trick xapian by giving it "inverse" sorting key so our - // ascending-date sorted threads stay in that order - tpath.back() = ((1U << (4 * seg_size)) - 1) - tpath.back(); - } + if (descending && container.parent) { + // trick xapian by giving it "inverse" sorting key so our + // ascending-date sorted threads stay in that order + tpath.back() = ((1U << (4 * seg_size)) - 1) - tpath.back(); + } - qmatch.thread_path = to_string(tpath, seg_size); - qmatch.thread_level = tpath.size() - 1; + qmatch.thread_path = to_string(tpath, seg_size); + qmatch.thread_level = tpath.size() - 1; - // ensure thread root comes before its children - if (descending) - qmatch.thread_path += ":z"; + // ensure thread root comes before its children + if (descending) + qmatch.thread_path += ":z"; - return true; + return true; } - static void -update_containers (Containers& children, bool descending, ThreadPath& tpath, - size_t seg_size, std::string& prev_subject) +update_containers(Containers& children, + bool descending, + ThreadPath& tpath, + size_t seg_size, + std::string& prev_subject) { - size_t idx{0}; + size_t idx{0}; - for (auto&& c: children) { - tpath.emplace_back(idx++); - if (c->query_match) { - update_container(*c, descending, tpath, seg_size, - prev_subject); + for (auto&& c : children) { + tpath.emplace_back(idx++); + if (c->query_match) { + update_container(*c, descending, tpath, seg_size, prev_subject); prev_subject = c->query_match->subject; - } - update_containers(c->children, descending, tpath, seg_size, - prev_subject); - tpath.pop_back(); - } + } + update_containers(c->children, descending, tpath, seg_size, prev_subject); + tpath.pop_back(); + } } static void -update_containers (ContainerVec& root_vec, bool descending, size_t n) +update_containers(ContainerVec& root_vec, bool descending, size_t n) { - ThreadPath tpath; - tpath.reserve (n); + ThreadPath tpath; + tpath.reserve(n); - const auto seg_size = static_cast(std::ceil(std::log2(n)/4.0)); - /*note: 4 == std::log2(16)*/ + const auto seg_size = static_cast(std::ceil(std::log2(n) / 4.0)); + /*note: 4 == std::log2(16)*/ - size_t idx{0}; - for (auto&& c: root_vec) { + size_t idx{0}; + for (auto&& c : root_vec) { tpath.emplace_back(idx++); std::string prev_subject; if (update_container(*c, descending, tpath, seg_size)) prev_subject = c->query_match->subject; - update_containers(c->children, descending, tpath, seg_size, - prev_subject); - tpath.pop_back(); - } + update_containers(c->children, descending, tpath, seg_size, prev_subject); + tpath.pop_back(); + } } - static void -sort_container (Container& container) +sort_container(Container& container) { - // 1. childless container. - if (container.children.empty()) - return; // no children; nothing to sort. + // 1. childless container. + if (container.children.empty()) + return; // no children; nothing to sort. - // 2. container with children. - // recurse, depth-first: sort the children - for (auto& child: container.children) - sort_container(*child); + // 2. container with children. + // recurse, depth-first: sort the children + for (auto& child : container.children) + sort_container(*child); - // now sort this level. - std::sort(container.children.begin(), container.children.end(), - [&](auto&& c1, auto&& c2) { - return c1->thread_date_key < c2->thread_date_key; - }); + // now sort this level. + std::sort(container.children.begin(), container.children.end(), [&](auto&& c1, auto&& c2) { + return c1->thread_date_key < c2->thread_date_key; + }); - // and 'bubble up' the date of the *newest* message with a date. We - // reasonably assume that it's later than its parent. - const auto& newest_date = container.children.back()->thread_date_key; - if (!newest_date.empty()) - container.thread_date_key = newest_date; + // and 'bubble up' the date of the *newest* message with a date. We + // reasonably assume that it's later than its parent. + const auto& newest_date = container.children.back()->thread_date_key; + if (!newest_date.empty()) + container.thread_date_key = newest_date; } - static void -sort_siblings (IdTable& id_table, bool descending) +sort_siblings(IdTable& id_table, bool descending) { - if (id_table.empty()) - return; + if (id_table.empty()) + return; - // unsorted vec of root containers. We can - // only sort these _after_ sorting the children. - ContainerVec root_vec; - for (auto&& item: id_table) { - if (!item.second.parent && !item.second.is_nuked) - root_vec.emplace_back(&item.second); - } + // unsorted vec of root containers. We can + // only sort these _after_ sorting the children. + ContainerVec root_vec; + for (auto&& item : id_table) { + if (!item.second.parent && !item.second.is_nuked) + root_vec.emplace_back(&item.second); + } - // now sort all threads _under_ the root set (by date/ascending) - for (auto&& c: root_vec) - sort_container(*c); + // now sort all threads _under_ the root set (by date/ascending) + for (auto&& c : root_vec) + sort_container(*c); - // and then sort the root set. - // - // The difference with the sub-root containers is that at the top-level, - // we can sort either in ascending or descending order, while on the - // subroot level it's always in ascending order. - // - // Note that unless we're testing, _xapian_ will handle - // the ascending/descending of the top level. - std::sort(root_vec.begin(), root_vec.end(), [&](auto&& c1, auto&& c2) { + // and then sort the root set. + // + // The difference with the sub-root containers is that at the top-level, + // we can sort either in ascending or descending order, while on the + // subroot level it's always in ascending order. + // + // Note that unless we're testing, _xapian_ will handle + // the ascending/descending of the top level. + std::sort(root_vec.begin(), root_vec.end(), [&](auto&& c1, auto&& c2) { #ifdef BUILD_TESTS - if (descending) - return c2->thread_date_key < c1->thread_date_key; - else + if (descending) + return c2->thread_date_key < c1->thread_date_key; + else #endif /*BUILD_TESTS*/ - return c1->thread_date_key < c2->thread_date_key; - }); + return c1->thread_date_key < c2->thread_date_key; + }); - // now all is sorted... final step is to determine thread paths and - // other flags. - update_containers (root_vec, descending, id_table.size()); + // now all is sorted... final step is to determine thread paths and + // other flags. + update_containers(root_vec, descending, id_table.size()); } static std::ostream& operator<<(std::ostream& os, const IdTable& id_table) { - os << "------------------------------------------------\n"; - for (auto&& item: id_table) { - os << item.first << " => " << item.second << "\n"; - } - os << "------------------------------------------------\n"; + os << "------------------------------------------------\n"; + for (auto&& item : id_table) { + os << item.first << " => " << item.second << "\n"; + } + os << "------------------------------------------------\n"; - std::set ids; - for (auto&& item: id_table) { - if (item.second.query_match) - ids.emplace(item.second.query_match->thread_path); - } + std::set ids; + for (auto&& item : id_table) { + if (item.second.query_match) + ids.emplace(item.second.query_match->thread_path); + } - for (auto&& id: ids) { - auto it = std::find_if(id_table.begin(), id_table.end(), [&](auto&& item) { - return item.second.query_match && - item.second.query_match->thread_path == id; - }); - assert(it != id_table.end()); - os << it->first << ": " << it->second << '\n'; - } - return os; + for (auto&& id : ids) { + auto it = std::find_if(id_table.begin(), id_table.end(), [&](auto&& item) { + return item.second.query_match && + item.second.query_match->thread_path == id; + }); + assert(it != id_table.end()); + os << it->first << ": " << it->second << '\n'; + } + return os; } - -template static void -calculate_threads_real (Results& qres, bool descending) +template +static void +calculate_threads_real(Results& qres, bool descending) { - // Step 1: build the id_table - auto id_table{determine_id_table(qres)}; + // Step 1: build the id_table + auto id_table{determine_id_table(qres)}; - if (g_test_verbose()) - std::cout << "*** id-table(1):\n" << id_table << "\n"; + if (g_test_verbose()) + std::cout << "*** id-table(1):\n" << id_table << "\n"; - // // Step 2: get the root set - // // Step 3: discard id_table - // Nope: id-table owns the containers. - // Step 4: prune empty containers - prune_empty_containers(id_table); + // // Step 2: get the root set + // // Step 3: discard id_table + // Nope: id-table owns the containers. + // Step 4: prune empty containers + prune_empty_containers(id_table); - // Step 5: group root-set by subject. - // Not implemented. + // Step 5: group root-set by subject. + // Not implemented. - // Step 6: we're done threading + // Step 6: we're done threading - // Step 7: sort siblings. The segment-size is the number of hex-digits - // in the thread-path string (so we can lexically compare them.) - sort_siblings(id_table, descending); + // Step 7: sort siblings. The segment-size is the number of hex-digits + // in the thread-path string (so we can lexically compare them.) + sort_siblings(id_table, descending); - // Step 7a:. update querymatches - for (auto&& item: id_table) { - Container& c{item.second}; - if (c.query_match) - c.query_match->thread_date = c.thread_date_key; - } - // if (g_test_verbose()) - // std::cout << "*** id-table(2):\n" << id_table << "\n"; + // Step 7a:. update querymatches + for (auto&& item : id_table) { + Container& c{item.second}; + if (c.query_match) + c.query_match->thread_date = c.thread_date_key; + } + // if (g_test_verbose()) + // std::cout << "*** id-table(2):\n" << id_table << "\n"; } void -Mu::calculate_threads (Mu::QueryResults& qres, bool descending) +Mu::calculate_threads(Mu::QueryResults& qres, bool descending) { - calculate_threads_real(qres, descending); + calculate_threads_real(qres, descending); } #ifdef BUILD_TESTS struct MockQueryResult { - MockQueryResult(const std::string& message_id_arg, - const std::string& date_arg, - const std::vector& refs_arg={}): - message_id_{message_id_arg}, - date_{date_arg}, - refs_{refs_arg} - {} - MockQueryResult(const std::string& message_id_arg, - const std::vector& refs_arg={}): - MockQueryResult(message_id_arg, "", refs_arg) {} - Option message_id() const { return message_id_;} - Option path() const { return path_;} - Option date() const { return date_;} - Option subject() const { return subject_;} - QueryMatch& query_match() { return query_match_;} - const QueryMatch& query_match() const { return query_match_;} - const std::vector& references() const { return refs_;} + MockQueryResult(const std::string& message_id_arg, + const std::string& date_arg, + const std::vector& refs_arg = {}) + : message_id_{message_id_arg}, date_{date_arg}, refs_{refs_arg} + { + } + MockQueryResult(const std::string& message_id_arg, + const std::vector& refs_arg = {}) + : MockQueryResult(message_id_arg, "", refs_arg) + { + } + Option message_id() const { return message_id_; } + Option path() const { return path_; } + Option date() const { return date_; } + Option subject() const { return subject_; } + QueryMatch& query_match() { return query_match_; } + const QueryMatch& query_match() const { return query_match_; } + const std::vector& references() const { return refs_; } - std::string path_; - std::string message_id_; - QueryMatch query_match_{}; - std::string date_; - std::string subject_; - std::vector refs_; + std::string path_; + std::string message_id_; + QueryMatch query_match_{}; + std::string date_; + std::string subject_; + std::vector refs_; }; using MockQueryResults = std::vector; - G_GNUC_UNUSED static std::ostream& operator<<(std::ostream& os, const MockQueryResults& qrs) { - for (auto&& mi: qrs) - os << mi.query_match().thread_path << " :: " - << mi.message_id().value_or("") << std::endl; + for (auto&& mi : qrs) + os << mi.query_match().thread_path << " :: " << mi.message_id().value_or("") + << std::endl; - return os; + return os; } static void -calculate_threads (MockQueryResults& qres, bool descending) +calculate_threads(MockQueryResults& qres, bool descending) { - calculate_threads_real(qres, descending); + calculate_threads_real(qres, descending); } using Expected = std::vector>; - static void -assert_thread_paths (const MockQueryResults& qrs, const Expected& expected) +assert_thread_paths(const MockQueryResults& qrs, const Expected& expected) { - for (auto&& exp: expected) { - auto it = std::find_if(qrs.begin(), qrs.end(), [&](auto&& qr){ - return qr.message_id().value_or("") == exp.first || - qr.path().value_or("") == exp.first; - }); - g_assert_true (it != qrs.end()); - g_assert_cmpstr(exp.second.c_str(), ==, - it->query_match().thread_path.c_str()); - } + for (auto&& exp : expected) { + auto it = std::find_if(qrs.begin(), qrs.end(), [&](auto&& qr) { + return qr.message_id().value_or("") == exp.first || + qr.path().value_or("") == exp.first; + }); + g_assert_true(it != qrs.end()); + g_assert_cmpstr(exp.second.c_str(), ==, it->query_match().thread_path.c_str()); + } } static void test_sort_ascending() { - auto results = MockQueryResults { - MockQueryResult{ "m1", "1", {"m2"} }, - MockQueryResult{ "m2", "2", {"m3"} }, - MockQueryResult{ "m3", "3", {}}, - MockQueryResult{ "m4", "4", {}} - }; + auto results = MockQueryResults{MockQueryResult{"m1", "1", {"m2"}}, + MockQueryResult{"m2", "2", {"m3"}}, + MockQueryResult{"m3", "3", {}}, + MockQueryResult{"m4", "4", {}}}; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "m1", "0:0:0"}, - { "m2", "0:0" }, - { "m3", "0" }, - { "m4", "1" } - }); + assert_thread_paths(results, {{"m1", "0:0:0"}, {"m2", "0:0"}, {"m3", "0"}, {"m4", "1"}}); } static void test_sort_descending() { - auto results = MockQueryResults { - MockQueryResult{ "m1", "1", {"m2"} }, - MockQueryResult{ "m2", "2", {"m3"} }, - MockQueryResult{ "m3", "3", {}}, - MockQueryResult{ "m4", "4", {}} - }; + auto results = MockQueryResults{MockQueryResult{"m1", "1", {"m2"}}, + MockQueryResult{"m2", "2", {"m3"}}, + MockQueryResult{"m3", "3", {}}, + MockQueryResult{"m4", "4", {}}}; - calculate_threads(results, true); + calculate_threads(results, true); - assert_thread_paths (results, { - { "m1", "1:f:f:z"}, - { "m2", "1:f:z" }, - { "m3", "1:z" }, - { "m4", "0:z" } - }); + assert_thread_paths(results, + {{"m1", "1:f:f:z"}, {"m2", "1:f:z"}, {"m3", "1:z"}, {"m4", "0:z"}}); } static void test_id_table_inconsistent() { - auto results = MockQueryResults { - MockQueryResult{ "m1", "1", {"m2"} }, // 1->2 - MockQueryResult{ "m2", "2", {"m1"} }, // 2->1 - MockQueryResult{ "m3", "3", {"m3"} }, // self ref - MockQueryResult{ "m4", "4", {"m3", "m5"} }, - MockQueryResult{ "m5", "5", {"m4", "m4"} }, // dup parent - }; + auto results = MockQueryResults{ + MockQueryResult{"m1", "1", {"m2"}}, // 1->2 + MockQueryResult{"m2", "2", {"m1"}}, // 2->1 + MockQueryResult{"m3", "3", {"m3"}}, // self ref + MockQueryResult{"m4", "4", {"m3", "m5"}}, + MockQueryResult{"m5", "5", {"m4", "m4"}}, // dup parent + }; - calculate_threads(results, false); - assert_thread_paths (results, { - { "m2", "0"}, - { "m1", "0:0"}, - { "m3", "1"}, - { "m5", "1:0"}, - { "m4", "1:0:0"}, - }); + calculate_threads(results, false); + assert_thread_paths(results, + { + {"m2", "0"}, + {"m1", "0:0"}, + {"m3", "1"}, + {"m5", "1:0"}, + {"m4", "1:0:0"}, + }); } static void test_dups_dup_last() { - MockQueryResult r1 { "m1", "1", {} }; - r1.query_match().flags |= QueryMatch::Flags::Leader; - r1.path_ = "/path1"; + MockQueryResult r1{"m1", "1", {}}; + r1.query_match().flags |= QueryMatch::Flags::Leader; + r1.path_ = "/path1"; - MockQueryResult r1_dup { "m1", "1", {} }; - r1_dup.query_match().flags |= QueryMatch::Flags::Duplicate; - r1_dup.path_ = "/path2"; + MockQueryResult r1_dup{"m1", "1", {}}; + r1_dup.query_match().flags |= QueryMatch::Flags::Duplicate; + r1_dup.path_ = "/path2"; - auto results = MockQueryResults {r1, r1_dup }; + auto results = MockQueryResults{r1, r1_dup}; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "/path1", "0"}, - { "/path2", "0:0" }, - }); + assert_thread_paths(results, + { + {"/path1", "0"}, + {"/path2", "0:0"}, + }); } static void test_dups_dup_first() { - // now dup becomes the leader; this will _demote_ - // r1. + // now dup becomes the leader; this will _demote_ + // r1. - MockQueryResult r1_dup { "m1", "1", {} }; - r1_dup.query_match().flags |= QueryMatch::Flags::Duplicate; - r1_dup.path_ = "/path1"; + MockQueryResult r1_dup{"m1", "1", {}}; + r1_dup.query_match().flags |= QueryMatch::Flags::Duplicate; + r1_dup.path_ = "/path1"; - MockQueryResult r1 { "m1", "1", {} }; - r1.query_match().flags |= QueryMatch::Flags::Leader; - r1.path_ = "/path2"; + MockQueryResult r1{"m1", "1", {}}; + r1.query_match().flags |= QueryMatch::Flags::Leader; + r1.path_ = "/path2"; - auto results = MockQueryResults { r1_dup, r1 }; + auto results = MockQueryResults{r1_dup, r1}; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "/path2", "0"}, - { "/path1", "0:0" }, - }); + assert_thread_paths(results, + { + {"/path2", "0"}, + {"/path1", "0:0"}, + }); } - static void test_do_not_prune_root_empty_with_children() { - // m7 should not be nuked - auto results = MockQueryResults { - MockQueryResult{ "x1", "1", {"m7"} }, - MockQueryResult{ "x2", "2", {"m7"} }, - }; + // m7 should not be nuked + auto results = MockQueryResults{ + MockQueryResult{"x1", "1", {"m7"}}, + MockQueryResult{"x2", "2", {"m7"}}, + }; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "x1", "0:0"}, - { "x2", "0:1" }, - }); + assert_thread_paths(results, + { + {"x1", "0:0"}, + {"x2", "0:1"}, + }); } static void test_prune_root_empty_with_child() { - // m7 should be nuked - auto results = MockQueryResults { - MockQueryResult{ "m1", "1", {"m7"} }, - }; + // m7 should be nuked + auto results = MockQueryResults{ + MockQueryResult{"m1", "1", {"m7"}}, + }; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "m1", "0"}, - }); + assert_thread_paths(results, + { + {"m1", "0"}, + }); } static void test_prune_empty_with_children() { - // m6 should be nuked - auto results = MockQueryResults { - MockQueryResult{ "m1", "1", {"m7", "m6"} }, - MockQueryResult{ "m2", "2", {"m7", "m6"} }, - }; + // m6 should be nuked + auto results = MockQueryResults{ + MockQueryResult{"m1", "1", {"m7", "m6"}}, + MockQueryResult{"m2", "2", {"m7", "m6"}}, + }; - calculate_threads(results, false); + calculate_threads(results, false); - assert_thread_paths (results, { - { "m1", "0:0"}, - { "m2", "0:1" }, - }); + assert_thread_paths(results, + { + {"m1", "0:0"}, + {"m2", "0:1"}, + }); } - static void test_thread_info_ascending() { - auto results = MockQueryResults { - MockQueryResult{ "m1", "5", {}}, - MockQueryResult{ "m2", "1", {}}, - MockQueryResult{ "m3", "3", {"m2"}}, - MockQueryResult{ "m4", "2", {"m2"}}, - // orphan siblings - MockQueryResult{ "m10", "6", {"m9"}}, - MockQueryResult{ "m11", "7", {"m9"}}, - }; - calculate_threads(results, false); + auto results = MockQueryResults{ + MockQueryResult{"m1", "5", {}}, + MockQueryResult{"m2", "1", {}}, + MockQueryResult{"m3", "3", {"m2"}}, + MockQueryResult{"m4", "2", {"m2"}}, + // orphan siblings + MockQueryResult{"m10", "6", {"m9"}}, + MockQueryResult{"m11", "7", {"m9"}}, + }; + calculate_threads(results, false); - assert_thread_paths (results, { - { "m2", "0" }, // 2 - { "m4", "0:0" }, // 2 - { "m3", "0:1" }, // 3 - { "m1", "1" }, // 5 + assert_thread_paths(results, + { + {"m2", "0"}, // 2 + {"m4", "0:0"}, // 2 + {"m3", "0:1"}, // 3 + {"m1", "1"}, // 5 - { "m10", "2:0" }, // 6 - { "m11", "2:1" }, // 7 - }); + {"m10", "2:0"}, // 6 + {"m11", "2:1"}, // 7 + }); - g_assert_true (results[0].query_match().has_flag( - QueryMatch::Flags::Root)); - g_assert_true (results[1].query_match().has_flag( - QueryMatch::Flags::Root | QueryMatch::Flags::HasChild)); - g_assert_true (results[2].query_match().has_flag( - QueryMatch::Flags::Last)); - g_assert_true (results[3].query_match().has_flag( - QueryMatch::Flags::First)); - g_assert_true (results[4].query_match().has_flag( - QueryMatch::Flags::Orphan | QueryMatch::Flags::First)); - g_assert_true (results[5].query_match().has_flag( - QueryMatch::Flags::Orphan | QueryMatch::Flags::Last)); + g_assert_true(results[0].query_match().has_flag(QueryMatch::Flags::Root)); + g_assert_true(results[1].query_match().has_flag(QueryMatch::Flags::Root | + QueryMatch::Flags::HasChild)); + g_assert_true(results[2].query_match().has_flag(QueryMatch::Flags::Last)); + g_assert_true(results[3].query_match().has_flag(QueryMatch::Flags::First)); + g_assert_true(results[4].query_match().has_flag(QueryMatch::Flags::Orphan | + QueryMatch::Flags::First)); + g_assert_true( + results[5].query_match().has_flag(QueryMatch::Flags::Orphan | QueryMatch::Flags::Last)); } static void test_thread_info_descending() { - auto results = MockQueryResults { - MockQueryResult{ "m1", "5", {}}, - MockQueryResult{ "m2", "1", {}}, - MockQueryResult{ "m3", "3", {"m2"}}, - MockQueryResult{ "m4", "2", {"m2"}}, - // orphan siblings - MockQueryResult{ "m10", "6", {"m9"}}, - MockQueryResult{ "m11", "7", {"m9"}}, - }; - calculate_threads(results, true/*descending*/); + auto results = MockQueryResults{ + MockQueryResult{"m1", "5", {}}, + MockQueryResult{"m2", "1", {}}, + MockQueryResult{"m3", "3", {"m2"}}, + MockQueryResult{"m4", "2", {"m2"}}, + // orphan siblings + MockQueryResult{"m10", "6", {"m9"}}, + MockQueryResult{"m11", "7", {"m9"}}, + }; + calculate_threads(results, true /*descending*/); - assert_thread_paths (results, { - { "m1", "1:z" }, // 5 - { "m2", "2:z" }, // 2 - { "m4", "2:f:z" }, // 2 - { "m3", "2:e:z" }, // 3 + assert_thread_paths(results, + { + {"m1", "1:z"}, // 5 + {"m2", "2:z"}, // 2 + {"m4", "2:f:z"}, // 2 + {"m3", "2:e:z"}, // 3 - { "m10", "0:f:z" }, // 6 - { "m11", "0:e:z" }, // 7 - }); - g_assert_true (results[0].query_match().has_flag( - QueryMatch::Flags::Root)); - g_assert_true (results[1].query_match().has_flag( - QueryMatch::Flags::Root | QueryMatch::Flags::HasChild)); - g_assert_true (results[2].query_match().has_flag( - QueryMatch::Flags::Last)); - g_assert_true (results[3].query_match().has_flag( - QueryMatch::Flags::First)); - - g_assert_true (results[4].query_match().has_flag( - QueryMatch::Flags::Orphan | QueryMatch::Flags::Last)); - g_assert_true (results[5].query_match().has_flag( - QueryMatch::Flags::Orphan | QueryMatch::Flags::First)); + {"m10", "0:f:z"}, // 6 + {"m11", "0:e:z"}, // 7 + }); + g_assert_true(results[0].query_match().has_flag(QueryMatch::Flags::Root)); + g_assert_true(results[1].query_match().has_flag(QueryMatch::Flags::Root | + QueryMatch::Flags::HasChild)); + g_assert_true(results[2].query_match().has_flag(QueryMatch::Flags::Last)); + g_assert_true(results[3].query_match().has_flag(QueryMatch::Flags::First)); + g_assert_true( + results[4].query_match().has_flag(QueryMatch::Flags::Orphan | QueryMatch::Flags::Last)); + g_assert_true(results[5].query_match().has_flag(QueryMatch::Flags::Orphan | + QueryMatch::Flags::First)); } - int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/threader/sort/ascending", test_sort_ascending); - g_test_add_func ("/threader/sort/decending", test_sort_descending); + g_test_add_func("/threader/sort/ascending", test_sort_ascending); + g_test_add_func("/threader/sort/decending", test_sort_descending); - g_test_add_func ("/threader/id-table-inconsistent", test_id_table_inconsistent); - g_test_add_func ("/threader/dups/dup-last", test_dups_dup_last); - g_test_add_func ("/threader/dups/dup-first", test_dups_dup_first); + g_test_add_func("/threader/id-table-inconsistent", test_id_table_inconsistent); + g_test_add_func("/threader/dups/dup-last", test_dups_dup_last); + g_test_add_func("/threader/dups/dup-first", test_dups_dup_first); - g_test_add_func ("/threader/prune/do-not-prune-root-empty-with-children", - test_do_not_prune_root_empty_with_children); - g_test_add_func ("/threader/prune/prune-root-empty-with-child", - test_prune_root_empty_with_child); - g_test_add_func ("/threader/prune/prune-empty-with-children", - test_prune_empty_with_children); + g_test_add_func("/threader/prune/do-not-prune-root-empty-with-children", + test_do_not_prune_root_empty_with_children); + g_test_add_func("/threader/prune/prune-root-empty-with-child", + test_prune_root_empty_with_child); + g_test_add_func("/threader/prune/prune-empty-with-children", + test_prune_empty_with_children); - g_test_add_func ("/threader/thread-info/ascending", - test_thread_info_ascending); - g_test_add_func ("/threader/thread-info/descending", - test_thread_info_descending); + g_test_add_func("/threader/thread-info/ascending", test_thread_info_ascending); + g_test_add_func("/threader/thread-info/descending", test_thread_info_descending); - return g_test_run (); + return g_test_run(); } catch (const std::runtime_error& re) { - std::cerr << re.what() << "\n"; - return 1; + std::cerr << re.what() << "\n"; + return 1; } catch (...) { - std::cerr << "caught exception\n"; - return 1; + std::cerr << "caught exception\n"; + return 1; } #endif /*BUILD_TESTS*/ diff --git a/lib/mu-query-threads.hh b/lib/mu-query-threads.hh index a179d9bd..5aab888d 100644 --- a/lib/mu-query-threads.hh +++ b/lib/mu-query-threads.hh @@ -34,7 +34,7 @@ namespace Mu { * @param qres query results * @param descending whether to sort the top-level in descending order */ -void calculate_threads (QueryResults& qres, bool descending); +void calculate_threads(QueryResults& qres, bool descending); } // namespace Mu diff --git a/lib/mu-query.cc b/lib/mu-query.cc index 59e99734..c9fcc6b5 100644 --- a/lib/mu-query.cc +++ b/lib/mu-query.cc @@ -38,249 +38,263 @@ using namespace Mu; struct Query::Private { - Private(const Store& store): store_{store}, - parser_{store_} {} - // New - //bool calculate_threads (Xapian::Enquire& enq, size maxnum); + Private(const Store& store) : store_{store}, parser_{store_} {} + // New + // bool calculate_threads (Xapian::Enquire& enq, size maxnum); - Xapian::Enquire make_enquire (const std::string& expr, - MuMsgFieldId sortfieldid, QueryFlags qflags) const; - Xapian::Enquire make_related_enquire (const StringSet& thread_ids, - MuMsgFieldId sortfieldid, QueryFlags qflags) const; + Xapian::Enquire + make_enquire(const std::string& expr, MuMsgFieldId sortfieldid, QueryFlags qflags) const; + Xapian::Enquire make_related_enquire(const StringSet& thread_ids, + MuMsgFieldId sortfieldid, + QueryFlags qflags) const; - Option run_threaded (QueryResults&& qres, Xapian::Enquire& enq, - QueryFlags qflags) const; - Option run_singular (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const; - Option run_related (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const; - Option run (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const; + Option + run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFlags qflags) const; + Option run_singular(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const; + Option run_related(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const; + Option run(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const; - const Store& store_; - const Parser parser_; + const Store& store_; + const Parser parser_; }; -Query::Query(const Store& store): - priv_{std::make_unique(store)} -{} +Query::Query(const Store& store) : priv_{std::make_unique(store)} {} Query::Query(Query&& other) = default; Query::~Query() = default; - static Xapian::Enquire& -maybe_sort (Xapian::Enquire& enq, MuMsgFieldId sortfieldid, QueryFlags qflags) +maybe_sort(Xapian::Enquire& enq, MuMsgFieldId sortfieldid, QueryFlags qflags) { - if (sortfieldid != MU_MSG_FIELD_ID_NONE) - enq.set_sort_by_value(static_cast(sortfieldid), - any_of(qflags & QueryFlags::Descending)); - return enq; + if (sortfieldid != MU_MSG_FIELD_ID_NONE) + enq.set_sort_by_value(static_cast(sortfieldid), + any_of(qflags & QueryFlags::Descending)); + return enq; } Xapian::Enquire -Query::Private::make_enquire (const std::string& expr, - MuMsgFieldId sortfieldid, QueryFlags qflags) const +Query::Private::make_enquire(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags) const { - Xapian::Enquire enq{store_.database()}; + Xapian::Enquire enq{store_.database()}; - if (expr.empty() || expr == R"("")") - enq.set_query(Xapian::Query::MatchAll); - else { - WarningVec warns; - const auto tree{parser_.parse(expr, warns)}; - for (auto&& w: warns) - g_warning ("query warning: %s", to_string(w).c_str()); - enq.set_query(xapian_query(tree)); - g_debug ("qtree: %s", to_string(tree).c_str()); - } + if (expr.empty() || expr == R"("")") + enq.set_query(Xapian::Query::MatchAll); + else { + WarningVec warns; + const auto tree{parser_.parse(expr, warns)}; + for (auto&& w : warns) + g_warning("query warning: %s", to_string(w).c_str()); + enq.set_query(xapian_query(tree)); + g_debug("qtree: %s", to_string(tree).c_str()); + } - return maybe_sort (enq, sortfieldid, qflags); + return maybe_sort(enq, sortfieldid, qflags); } Xapian::Enquire -Query::Private::make_related_enquire (const StringSet& thread_ids, - MuMsgFieldId sortfieldid, QueryFlags qflags) const +Query::Private::make_related_enquire(const StringSet& thread_ids, + MuMsgFieldId sortfieldid, + QueryFlags qflags) const { - Xapian::Enquire enq{store_.database()}; - static std::string pfx (1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID)); + Xapian::Enquire enq{store_.database()}; + static std::string pfx(1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID)); - std::vector qvec; - for (auto&& t: thread_ids) - qvec.emplace_back(pfx + t); - Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()}; - enq.set_query(qr); - - return maybe_sort (enq, sortfieldid, qflags); + std::vector qvec; + for (auto&& t : thread_ids) + qvec.emplace_back(pfx + t); + Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()}; + enq.set_query(qr); + return maybe_sort(enq, sortfieldid, qflags); } -struct ThreadKeyMaker: public Xapian::KeyMaker { - ThreadKeyMaker (const QueryMatches& matches): match_info_(matches) {} - std::string operator()(const Xapian::Document& doc) const override { - const auto it{match_info_.find(doc.get_docid())}; - return (it == match_info_.end()) ? "" : it->second.thread_path; - } - const QueryMatches& match_info_; +struct ThreadKeyMaker : public Xapian::KeyMaker { + ThreadKeyMaker(const QueryMatches& matches) : match_info_(matches) {} + std::string operator()(const Xapian::Document& doc) const override + { + const auto it{match_info_.find(doc.get_docid())}; + return (it == match_info_.end()) ? "" : it->second.thread_path; + } + const QueryMatches& match_info_; }; Option -Query::Private::run_threaded (QueryResults&& qres, Xapian::Enquire& enq, - QueryFlags qflags) const +Query::Private::run_threaded(QueryResults&& qres, Xapian::Enquire& enq, QueryFlags qflags) const { - const auto descending{any_of(qflags & QueryFlags::Descending)}; + const auto descending{any_of(qflags & QueryFlags::Descending)}; - calculate_threads(qres, descending); + calculate_threads(qres, descending); - ThreadKeyMaker key_maker{qres.query_matches()}; - enq.set_sort_by_key(&key_maker, descending); + ThreadKeyMaker key_maker{qres.query_matches()}; + enq.set_sort_by_key(&key_maker, descending); - DeciderInfo minfo; - minfo.matches = qres.query_matches(); - auto mset{enq.get_mset(0, store_.size(), {}, - make_thread_decider(qflags, minfo).get())}; - mset.fetch(); + DeciderInfo minfo; + minfo.matches = qres.query_matches(); + auto mset{enq.get_mset(0, store_.size(), {}, make_thread_decider(qflags, minfo).get())}; + mset.fetch(); - return QueryResults{mset, std::move(qres.query_matches())}; + return QueryResults{mset, std::move(qres.query_matches())}; } - Option -Query::Private::run_singular (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const +Query::Private::run_singular(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const { - // i.e. a query _without_ related messages, but still possibly - // with threading. - // - // In the threading case, the sortfield-id is ignored, we always sort by - // date (since threading the threading results are always by date.) + // i.e. a query _without_ related messages, but still possibly + // with threading. + // + // In the threading case, the sortfield-id is ignored, we always sort by + // date (since threading the threading results are always by date.) - const auto singular_qflags{qflags | QueryFlags::Leader}; - const auto threading{any_of(qflags & QueryFlags::Threading)}; + const auto singular_qflags{qflags | QueryFlags::Leader}; + const auto threading{any_of(qflags & QueryFlags::Threading)}; - DeciderInfo minfo{}; + DeciderInfo minfo{}; #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wextra" - auto enq{make_enquire(expr, threading ? MU_MSG_FIELD_ID_DATE : sortfieldid, qflags)}; - #pragma GCC diagnostic ignored "-Wswitch-default" +#pragma GCC diagnostic ignored "-Wextra" + auto enq{make_enquire(expr, threading ? MU_MSG_FIELD_ID_DATE : sortfieldid, qflags)}; +#pragma GCC diagnostic ignored "-Wswitch-default" #pragma GCC diagnostic pop - auto mset{enq.get_mset(0, maxnum, {}, make_leader_decider(singular_qflags, minfo).get())}; - mset.fetch(); + auto mset{enq.get_mset(0, maxnum, {}, make_leader_decider(singular_qflags, minfo).get())}; + mset.fetch(); - auto qres{QueryResults{mset, std::move(minfo.matches)}}; + auto qres{QueryResults{mset, std::move(minfo.matches)}}; - return threading ? run_threaded(std::move(qres), enq, qflags) : qres; + return threading ? run_threaded(std::move(qres), enq, qflags) : qres; } static Option -opt_string(const Xapian::Document& doc, MuMsgFieldId id) noexcept try { - auto&& val{doc.get_value(id)}; - return val.empty() ? Nothing : Some(val); -} MU_XAPIAN_CATCH_BLOCK_RETURN (Nothing); - -Option -Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const +opt_string(const Xapian::Document& doc, MuMsgFieldId id) noexcept { - // i.e. a query _with_ related messages and possibly with threading. - // - // In the threading case, the sortfield-id is ignored, we always sort by - // date (since threading the threading results are always by date.); - // moreover, in either threaded or non-threaded case, we sort the first - // ("leader") query by date, i.e, we prefer the newest or oldest - // (descending) messages. - const auto leader_qflags{QueryFlags::Leader | qflags}; - const auto threading{any_of(qflags & QueryFlags::Threading)}; - - // Run our first, "leader" query - DeciderInfo minfo{}; - auto enq{make_enquire(expr, MU_MSG_FIELD_ID_DATE, leader_qflags)}; - const auto mset{enq.get_mset(0, maxnum, {}, - make_leader_decider(leader_qflags, minfo).get())}; - - // Gather the thread-ids we found - mset.fetch(); - for (auto it = mset.begin(); it != mset.end(); ++it) { - auto thread_id{opt_string(it.get_document(), MU_MSG_FIELD_ID_THREAD_ID)}; - if (thread_id) - minfo.thread_ids.emplace(std::move(*thread_id)); - } - - // Now, determine the "related query". - // - // In the threaded-case, we search among _all_ messages, since complete - // threads are preferred; no need to sort in that case since the search - // is unlimited and the sorting happens during threading. - auto r_enq{make_related_enquire(minfo.thread_ids, - threading ? MU_MSG_FIELD_ID_NONE : sortfieldid, qflags)}; - const auto r_mset{r_enq.get_mset(0, threading ? store_.size() : maxnum, - {}, make_related_decider(qflags, minfo).get())}; - auto qres{QueryResults{r_mset, std::move(minfo.matches)}}; - return threading ? run_threaded(std::move(qres), r_enq, qflags) : qres; + std::string val = xapian_try([&] { return doc.get_value(id); }, std::string{""}); + if (val.empty()) + return Nothing; + else + return Some(std::move(val)); } +Option +Query::Private::run_related(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const +{ + // i.e. a query _with_ related messages and possibly with threading. + // + // In the threading case, the sortfield-id is ignored, we always sort by + // date (since threading the threading results are always by date.); + // moreover, in either threaded or non-threaded case, we sort the first + // ("leader") query by date, i.e, we prefer the newest or oldest + // (descending) messages. + const auto leader_qflags{QueryFlags::Leader | qflags}; + const auto threading{any_of(qflags & QueryFlags::Threading)}; + + // Run our first, "leader" query + DeciderInfo minfo{}; + auto enq{make_enquire(expr, MU_MSG_FIELD_ID_DATE, leader_qflags)}; + const auto mset{ + enq.get_mset(0, maxnum, {}, make_leader_decider(leader_qflags, minfo).get())}; + + // Gather the thread-ids we found + mset.fetch(); + for (auto it = mset.begin(); it != mset.end(); ++it) { + auto thread_id{opt_string(it.get_document(), MU_MSG_FIELD_ID_THREAD_ID)}; + if (thread_id) + minfo.thread_ids.emplace(std::move(*thread_id)); + } + + // Now, determine the "related query". + // + // In the threaded-case, we search among _all_ messages, since complete + // threads are preferred; no need to sort in that case since the search + // is unlimited and the sorting happens during threading. + auto r_enq{make_related_enquire(minfo.thread_ids, + threading ? MU_MSG_FIELD_ID_NONE : sortfieldid, + qflags)}; + const auto r_mset{r_enq.get_mset(0, + threading ? store_.size() : maxnum, + {}, + make_related_decider(qflags, minfo).get())}; + auto qres{QueryResults{r_mset, std::move(minfo.matches)}}; + return threading ? run_threaded(std::move(qres), r_enq, qflags) : qres; +} Option -Query::Private::run (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const +Query::Private::run(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const { - const auto eff_maxnum{maxnum == 0 ? store_.size() : maxnum}; + const auto eff_maxnum{maxnum == 0 ? store_.size() : maxnum}; #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wextra" - const auto eff_sortfield{sortfieldid == MU_MSG_FIELD_ID_NONE ? - MU_MSG_FIELD_ID_DATE : sortfieldid }; +#pragma GCC diagnostic ignored "-Wextra" + const auto eff_sortfield{sortfieldid == MU_MSG_FIELD_ID_NONE ? MU_MSG_FIELD_ID_DATE + : sortfieldid}; #pragma GCC diagnostic pop - if (any_of(qflags & QueryFlags::IncludeRelated)) - return run_related (expr, eff_sortfield, qflags, eff_maxnum); - else - return run_singular(expr, eff_sortfield, qflags, eff_maxnum); + if (any_of(qflags & QueryFlags::IncludeRelated)) + return run_related(expr, eff_sortfield, qflags, eff_maxnum); + else + return run_singular(expr, eff_sortfield, qflags, eff_maxnum); } - Option -Query::run (const std::string& expr, MuMsgFieldId sortfieldid, - QueryFlags qflags, size_t maxnum) const try -{ - // some flags are for internal use only. - g_return_val_if_fail (none_of(qflags & QueryFlags::Leader), Nothing); +Query::run(const std::string& expr, + MuMsgFieldId sortfieldid, + QueryFlags qflags, + size_t maxnum) const +try { + // some flags are for internal use only. + g_return_val_if_fail(none_of(qflags & QueryFlags::Leader), Nothing); - StopWatch sw{format("ran query '%s'; related: %s; threads: %s; max-size: %zu", - expr.c_str(), - any_of(qflags & QueryFlags::IncludeRelated) ? "yes" : "no", - any_of(qflags & QueryFlags::Threading) ? "yes" : "no", - maxnum)}; + StopWatch sw{format("ran query '%s'; related: %s; threads: %s; max-size: %zu", + expr.c_str(), + any_of(qflags & QueryFlags::IncludeRelated) ? "yes" : "no", + any_of(qflags & QueryFlags::Threading) ? "yes" : "no", + maxnum)}; - return priv_->run(expr, sortfieldid, qflags, maxnum); + return priv_->run(expr, sortfieldid, qflags, maxnum); } catch (...) { - return Nothing; + return Nothing; } - size_t -Query::count (const std::string& expr) const try +Query::count(const std::string& expr) const { - const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})}; - auto mset{enq.get_mset(0, priv_->store_.size())}; - mset.fetch(); - - return mset.size(); - -}MU_XAPIAN_CATCH_BLOCK_RETURN (0); - - + return xapian_try( + [&] { + const auto enq{priv_->make_enquire(expr, MU_MSG_FIELD_ID_NONE, {})}; + auto mset{enq.get_mset(0, priv_->store_.size())}; + mset.fetch(); + return mset.size(); + }, + 0); +} std::string -Query::parse (const std::string& expr, bool xapian) const +Query::parse(const std::string& expr, bool xapian) const { - WarningVec warns; - const auto tree{priv_->parser_.parse(expr, warns)}; - for (auto&& w: warns) - g_warning ("query warning: %s", to_string(w).c_str()); + WarningVec warns; + const auto tree{priv_->parser_.parse(expr, warns)}; + for (auto&& w : warns) + g_warning("query warning: %s", to_string(w).c_str()); - if (xapian) - return xapian_query(tree).get_description(); - else - return to_string(tree); + if (xapian) + return xapian_query(tree).get_description(); + else + return to_string(tree); } diff --git a/lib/mu-query.hh b/lib/mu-query.hh index 07e6003b..c6c7e727 100644 --- a/lib/mu-query.hh +++ b/lib/mu-query.hh @@ -27,70 +27,69 @@ #include #include -namespace Mu -{ +namespace Mu { -class Query -{ - public: - /** - * Construct a new Query instance. - * - * @param store a MuStore object - */ - Query (const Store &store); - /** - * DTOR - * - */ - ~Query(); +class Query { + public: + /** + * Construct a new Query instance. + * + * @param store a MuStore object + */ + Query(const Store& store); + /** + * DTOR + * + */ + ~Query(); - /** - * Move CTOR - * - * @param other - */ - Query (Query &&other); + /** + * Move CTOR + * + * @param other + */ + Query(Query&& other); - /** - * Run a query on the store - * - * @param expr the search expression - * @param sortfieldid the sortfield-id. If the field is NONE, sort by DATE - * @param flags query flags - * @param maxnum maximum number of results to return. 0 for 'no limit' - * - * @return the query-results, or Nothing in case of error. - */ - Option run (const std::string &expr = "", - MuMsgFieldId sortfieldid = MU_MSG_FIELD_ID_NONE, - QueryFlags flags = QueryFlags::None, size_t maxnum = 0) const; + /** + * Run a query on the store + * + * @param expr the search expression + * @param sortfieldid the sortfield-id. If the field is NONE, sort by DATE + * @param flags query flags + * @param maxnum maximum number of results to return. 0 for 'no limit' + * + * @return the query-results, or Nothing in case of error. + */ + Option run(const std::string& expr = "", + MuMsgFieldId sortfieldid = MU_MSG_FIELD_ID_NONE, + QueryFlags flags = QueryFlags::None, + size_t maxnum = 0) const; - /** - * run a Xapian query to count the number of matches; for the syntax, please - * refer to the mu-query manpage - * - * @param expr the search expression; use "" to match all messages - * - * @return the number of matches - */ - size_t count (const std::string &expr = "") const; + /** + * run a Xapian query to count the number of matches; for the syntax, please + * refer to the mu-query manpage + * + * @param expr the search expression; use "" to match all messages + * + * @return the number of matches + */ + size_t count(const std::string& expr = "") const; - /** - * For debugging, get the internal string representation of the parsed - * query - * - * @param expr a xapian search expression - * @param xapian if true, show Xapian's internal representation, - * otherwise, mu's. + /** + * For debugging, get the internal string representation of the parsed + * query + * + * @param expr a xapian search expression + * @param xapian if true, show Xapian's internal representation, + * otherwise, mu's. - * @return the string representation of the query - */ - std::string parse (const std::string &expr, bool xapian) const; + * @return the string representation of the query + */ + std::string parse(const std::string& expr, bool xapian) const; - private: - struct Private; - std::unique_ptr priv_; + private: + struct Private; + std::unique_ptr priv_; }; } // namespace Mu diff --git a/lib/mu-runtime.cc b/lib/mu-runtime.cc index 491b9f22..b3b0e602 100644 --- a/lib/mu-runtime.cc +++ b/lib/mu-runtime.cc @@ -27,96 +27,91 @@ #include static std::unordered_map RuntimePaths; -constexpr auto PartsDir = "parts"; -constexpr auto LogDir = "log"; -constexpr auto XapianDir = "xapian"; -constexpr auto MuName = "mu"; -constexpr auto Bookmarks = "bookmarks"; +constexpr auto PartsDir = "parts"; +constexpr auto LogDir = "log"; +constexpr auto XapianDir = "xapian"; +constexpr auto MuName = "mu"; +constexpr auto Bookmarks = "bookmarks"; static const std::string Sepa{G_DIR_SEPARATOR_S}; - static void -init_paths_xdg () +init_paths_xdg() { - RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() + - Sepa + MuName + Sepa + XapianDir); - RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, g_get_user_cache_dir() + - Sepa + MuName); - RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() + - Sepa + MuName + Sepa + PartsDir); - RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() + - Sepa + MuName); - RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, g_get_user_config_dir() + - Sepa + MuName); + RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, + g_get_user_cache_dir() + Sepa + MuName + Sepa + XapianDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, g_get_user_cache_dir() + Sepa + MuName); + RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, + g_get_user_cache_dir() + Sepa + MuName + Sepa + PartsDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() + Sepa + MuName); + RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, g_get_user_config_dir() + Sepa + MuName); } static void -init_paths_muhome (const char *muhome) +init_paths_muhome(const char* muhome) { - RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir); - RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, muhome); + RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, muhome); RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, muhome + Sepa + PartsDir); - RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir); + RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir); RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, muhome + Sepa + Bookmarks); } gboolean -mu_runtime_init (const char* muhome, const char *name, gboolean debug) +mu_runtime_init(const char* muhome, const char* name, gboolean debug) { - g_return_val_if_fail (RuntimePaths.empty(), FALSE); - g_return_val_if_fail (name, FALSE); + g_return_val_if_fail(RuntimePaths.empty(), FALSE); + g_return_val_if_fail(name, FALSE); - setlocale (LC_ALL, ""); + setlocale(LC_ALL, ""); - if (muhome) - init_paths_muhome (muhome); - else - init_paths_xdg(); + if (muhome) + init_paths_muhome(muhome); + else + init_paths_xdg(); - for (const auto& d: RuntimePaths ) { - char* dir; - if (d.first == MU_RUNTIME_PATH_BOOKMARKS) // special case - dir = g_path_get_dirname (d.second.c_str()); - else - dir = g_strdup (d.second.c_str()); + for (const auto& d : RuntimePaths) { + char* dir; + if (d.first == MU_RUNTIME_PATH_BOOKMARKS) // special case + dir = g_path_get_dirname(d.second.c_str()); + else + dir = g_strdup(d.second.c_str()); - auto ok = mu_util_create_dir_maybe (dir, 0700, TRUE); - if (!ok) { - g_critical ("failed to create %s", dir); - g_free (dir); - mu_runtime_uninit(); - return FALSE; - } - g_free (dir); - } + auto ok = mu_util_create_dir_maybe(dir, 0700, TRUE); + if (!ok) { + g_critical("failed to create %s", dir); + g_free(dir); + mu_runtime_uninit(); + return FALSE; + } + g_free(dir); + } - const auto log_path = RuntimePaths[MU_RUNTIME_PATH_LOGDIR] + - Sepa + name + ".log"; + const auto log_path = RuntimePaths[MU_RUNTIME_PATH_LOGDIR] + Sepa + name + ".log"; - using namespace Mu; - LogOptions opts{LogOptions::None}; - if (debug) - opts |= (LogOptions::Debug | LogOptions::None); + using namespace Mu; + LogOptions opts{LogOptions::None}; + if (debug) + opts |= (LogOptions::Debug | LogOptions::None); - Mu::log_init(log_path, opts); + Mu::log_init(log_path, opts); - return TRUE; + return TRUE; } void -mu_runtime_uninit (void) +mu_runtime_uninit(void) { - RuntimePaths.clear(); - Mu::log_uninit(); + RuntimePaths.clear(); + Mu::log_uninit(); } const char* -mu_runtime_path (MuRuntimePath path) +mu_runtime_path(MuRuntimePath path) { - const auto it = RuntimePaths.find (path); - if (it == RuntimePaths.end()) - return NULL; - else - return it->second.c_str(); + const auto it = RuntimePaths.find(path); + if (it == RuntimePaths.end()) + return NULL; + else + return it->second.c_str(); } diff --git a/lib/mu-runtime.hh b/lib/mu-runtime.hh index b9b7258d..0f0d4107 100644 --- a/lib/mu-runtime.hh +++ b/lib/mu-runtime.hh @@ -35,22 +35,20 @@ G_BEGIN_DECLS * * @return TRUE if succeeded, FALSE in case of error */ -gboolean mu_runtime_init (const char *muhome, const char *name, - gboolean debug); +gboolean mu_runtime_init(const char* muhome, const char* name, gboolean debug); /** * free all resources * */ -void mu_runtime_uninit (void); - +void mu_runtime_uninit(void); typedef enum { - MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */ - MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */ - MU_RUNTIME_PATH_CACHE, /* mu cache path */ - MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */ - MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */ + MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */ + MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */ + MU_RUNTIME_PATH_CACHE, /* mu cache path */ + MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */ + MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */ MU_RUNTIME_PATH_NUM } MuRuntimePath; @@ -61,7 +59,7 @@ typedef enum { * @return ma string which should be not be modified/freed, or NULL in * case of error. */ -const char* mu_runtime_path (MuRuntimePath path); +const char* mu_runtime_path(MuRuntimePath path); G_END_DECLS diff --git a/lib/mu-script.cc b/lib/mu-script.cc index afcfd8e4..ea9000af 100644 --- a/lib/mu-script.cc +++ b/lib/mu-script.cc @@ -43,117 +43,114 @@ * the values will be *freed* when MuScriptInfo is freed */ struct MuScriptInfo { - char *_name; /* filename-sans-extension */ - char *_path; /* full path to script */ - char *_oneline; /* one-line description */ - char *_descr; /* longer description */ + char* _name; /* filename-sans-extension */ + char* _path; /* full path to script */ + char* _oneline; /* one-line description */ + char* _descr; /* longer description */ }; - /* create a new MuScriptInfo* object*/ static MuScriptInfo* -script_info_new (void) +script_info_new(void) { - return g_slice_new0 (MuScriptInfo); + return g_slice_new0(MuScriptInfo); } /* destroy a MuScriptInfo* object */ static void -script_info_destroy (MuScriptInfo *msi) +script_info_destroy(MuScriptInfo* msi) { if (!msi) return; - g_free (msi->_name); - g_free (msi->_path); - g_free (msi->_oneline); - g_free (msi->_descr); + g_free(msi->_name); + g_free(msi->_path); + g_free(msi->_oneline); + g_free(msi->_descr); - g_slice_free (MuScriptInfo, msi); + g_slice_free(MuScriptInfo, msi); } /* compare two MuScripInfo* objects (for sorting) */ static int -script_info_cmp (MuScriptInfo *msi1, MuScriptInfo *msi2) +script_info_cmp(MuScriptInfo* msi1, MuScriptInfo* msi2) { - return strcmp (msi1->_name, msi2->_name); - + return strcmp(msi1->_name, msi2->_name); } const char* -mu_script_info_name (MuScriptInfo *msi) +mu_script_info_name(MuScriptInfo* msi) { - g_return_val_if_fail (msi, NULL); + g_return_val_if_fail(msi, NULL); return msi->_name; } const char* -mu_script_info_path (MuScriptInfo *msi) +mu_script_info_path(MuScriptInfo* msi) { - g_return_val_if_fail (msi, NULL); + g_return_val_if_fail(msi, NULL); return msi->_path; } const char* -mu_script_info_one_line (MuScriptInfo *msi) +mu_script_info_one_line(MuScriptInfo* msi) { - g_return_val_if_fail (msi, NULL); + g_return_val_if_fail(msi, NULL); return msi->_oneline; } const char* -mu_script_info_description (MuScriptInfo *msi) +mu_script_info_description(MuScriptInfo* msi) { - g_return_val_if_fail (msi, NULL); + g_return_val_if_fail(msi, NULL); return msi->_descr; } - gboolean -mu_script_info_matches_regex (MuScriptInfo *msi, const char *rxstr, - GError **err) +mu_script_info_matches_regex(MuScriptInfo* msi, const char* rxstr, GError** err) { - GRegex *rx; + GRegex* rx; gboolean match; - g_return_val_if_fail (msi, FALSE); - g_return_val_if_fail (rxstr, FALSE); + g_return_val_if_fail(msi, FALSE); + g_return_val_if_fail(rxstr, FALSE); - rx = g_regex_new (rxstr, - (GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE), - (GRegexMatchFlags)0, err); + rx = g_regex_new(rxstr, + (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE), + (GRegexMatchFlags)0, + err); if (!rx) return FALSE; match = FALSE; if (msi->_name) - match = g_regex_match (rx, msi->_name, (GRegexMatchFlags)0, NULL); + match = g_regex_match(rx, msi->_name, (GRegexMatchFlags)0, NULL); if (!match && msi->_oneline) - match = g_regex_match (rx, msi->_oneline,(GRegexMatchFlags)0, NULL); + match = g_regex_match(rx, msi->_oneline, (GRegexMatchFlags)0, NULL); return match; } void -mu_script_info_list_destroy (GSList *lst) +mu_script_info_list_destroy(GSList* lst) { g_slist_free_full(lst, (GDestroyNotify)script_info_destroy); } - -static GIOChannel * -open_channel (const char *path) +static GIOChannel* +open_channel(const char* path) { - GError *err; - GIOChannel *io_chan; + GError* err; + GIOChannel* io_chan; err = NULL; - io_chan = g_io_channel_new_file (path, "r", &err); + io_chan = g_io_channel_new_file(path, "r", &err); if (!io_chan) { - g_warning ("failed to open '%s': %s", path, - err ? err->message : "something went wrong"); - g_clear_error (&err); + g_warning("failed to open '%s': %s", + path, + err ? err->message : "something went wrong"); + g_clear_error(&err); return NULL; } @@ -161,137 +158,131 @@ open_channel (const char *path) } static void -end_channel (GIOChannel *io_chan) +end_channel(GIOChannel* io_chan) { GIOStatus status; - GError *err; + GError* err; err = NULL; - status = g_io_channel_shutdown (io_chan, FALSE, - &err); + status = g_io_channel_shutdown(io_chan, FALSE, &err); if (status != G_IO_STATUS_NORMAL) { - g_warning ("failed to shutdown io-channel: %s", - err ? err->message : "something went wrong"); - g_clear_error (&err); + g_warning("failed to shutdown io-channel: %s", + err ? err->message : "something went wrong"); + g_clear_error(&err); } - g_io_channel_unref (io_chan); + g_io_channel_unref(io_chan); } - - static gboolean -get_descriptions (MuScriptInfo *msi, const char *prefix) +get_descriptions(MuScriptInfo* msi, const char* prefix) { - GIOStatus io_status; - GIOChannel *script_io; - GError *err; + GIOStatus io_status; + GIOChannel* script_io; + GError* err; char *line, *descr, *oneline; if (!prefix) return TRUE; /* not an error */ - if (!(script_io = open_channel (msi->_path))) + if (!(script_io = open_channel(msi->_path))) return FALSE; err = NULL; line = descr = oneline = NULL; do { - g_free (line); - io_status = g_io_channel_read_line (script_io, &line, - NULL, NULL, &err); + g_free(line); + io_status = g_io_channel_read_line(script_io, &line, NULL, NULL, &err); if (io_status != G_IO_STATUS_NORMAL) break; - if (!g_str_has_prefix (line, prefix)) + if (!g_str_has_prefix(line, prefix)) continue; if (!oneline) - oneline = g_strdup (line + strlen (prefix)); + oneline = g_strdup(line + strlen(prefix)); else { - char *tmp; - tmp = descr; - descr = g_strdup_printf - ("%s%s", descr ? descr : "", - line + strlen(prefix)); - g_free (tmp); + char* tmp; + tmp = descr; + descr = g_strdup_printf("%s%s", descr ? descr : "", line + strlen(prefix)); + g_free(tmp); } } while (TRUE); if (io_status != G_IO_STATUS_EOF) { - g_warning ("error reading %s: %s", msi->_path, - err ? err->message : "something went wrong"); - g_clear_error (&err); + g_warning("error reading %s: %s", + msi->_path, + err ? err->message : "something went wrong"); + g_clear_error(&err); } - end_channel (script_io); + end_channel(script_io); msi->_oneline = oneline; msi->_descr = descr; return TRUE; } - - GSList* -mu_script_get_script_info_list (const char *path, const char *ext, - const char *descprefix, GError **err) +mu_script_get_script_info_list(const char* path, + const char* ext, + const char* descprefix, + GError** err) { - DIR *dir; - GSList *lst; - struct dirent *dentry; + DIR* dir; + GSList* lst; + struct dirent* dentry; - g_return_val_if_fail (path, NULL); + g_return_val_if_fail(path, NULL); - dir = opendir (path); + dir = opendir(path); if (!dir) { - mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_OPEN, - "failed to open '%s': %s", - path, g_strerror(errno)); + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_OPEN, + "failed to open '%s': %s", + path, + g_strerror(errno)); return NULL; } /* create a list of names, paths */ lst = NULL; - while ((dentry = readdir (dir))) { - MuScriptInfo *msi; + while ((dentry = readdir(dir))) { + MuScriptInfo* msi; /* only consider files with certain extensions, * if ext != NULL */ - if (ext && !g_str_has_suffix (dentry->d_name, ext)) + if (ext && !g_str_has_suffix(dentry->d_name, ext)) continue; - msi = script_info_new (); - msi->_name = g_strdup (dentry->d_name); + msi = script_info_new(); + msi->_name = g_strdup(dentry->d_name); if (ext) /* strip the extension */ msi->_name[strlen(msi->_name) - strlen(ext)] = '\0'; - msi->_path = g_strdup_printf ("%s%c%s", path, G_DIR_SEPARATOR, - dentry->d_name); + msi->_path = g_strdup_printf("%s%c%s", path, G_DIR_SEPARATOR, dentry->d_name); /* set the one-line and long description */ - get_descriptions (msi, descprefix); - lst = g_slist_prepend (lst, msi); + get_descriptions(msi, descprefix); + lst = g_slist_prepend(lst, msi); } - closedir (dir); /* ignore error checking... */ + closedir(dir); /* ignore error checking... */ - return g_slist_sort (lst, (GCompareFunc)script_info_cmp); + return g_slist_sort(lst, (GCompareFunc)script_info_cmp); } - MuScriptInfo* -mu_script_find_script_with_name (GSList *lst, const char *name) +mu_script_find_script_with_name(GSList* lst, const char* name) { - GSList *cur; + GSList* cur; - g_return_val_if_fail (name, NULL); + g_return_val_if_fail(name, NULL); - for (cur = lst; cur; cur = g_slist_next (cur)) { - - MuScriptInfo *msi; + for (cur = lst; cur; cur = g_slist_next(cur)) { + MuScriptInfo* msi; msi = (MuScriptInfo*)cur->data; - if (g_strcmp0 (name, mu_script_info_name (msi)) == 0) + if (g_strcmp0(name, mu_script_info_name(msi)) == 0) return msi; } @@ -300,60 +291,57 @@ mu_script_find_script_with_name (GSList *lst, const char *name) #ifdef BUILD_GUILE static void -guile_shell (void *closure, int argc, char **argv) +guile_shell(void* closure, int argc, char** argv) { - scm_shell (argc, argv); + scm_shell(argc, argv); } gboolean -mu_script_guile_run (MuScriptInfo *msi, const char *muhome, - const char **args, GError **err) +mu_script_guile_run(MuScriptInfo* msi, const char* muhome, const char** args, GError** err) { - const char *s; - char *mainargs, *expr; - char **argv; + const char* s; + char * mainargs, *expr; + char** argv; - g_return_val_if_fail (msi, FALSE); - g_return_val_if_fail (muhome, FALSE); + g_return_val_if_fail(msi, FALSE); + g_return_val_if_fail(muhome, FALSE); - argv = g_new0 (char*, 6); + argv = g_new0(char*, 6); argv[0] = g_strdup(GUILE_BINARY); argv[1] = g_strdup("-l"); - if (access (mu_script_info_path (msi), R_OK) != 0) { - mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_READ, - "failed to read script: %s", - g_strerror(errno)); - return FALSE; + if (access(mu_script_info_path(msi), R_OK) != 0) { + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_READ, + "failed to read script: %s", + g_strerror(errno)); + return FALSE; } - s = mu_script_info_path (msi); - argv[2] = g_strdup (s ? s : ""); + s = mu_script_info_path(msi); + argv[2] = g_strdup(s ? s : ""); - mainargs = mu_str_quoted_from_strv (args); - expr = g_strdup_printf ( - "(main '(\"%s\" \"--muhome=%s\" %s))", - mu_script_info_name (msi), - muhome, - mainargs ? mainargs : ""); + mainargs = mu_str_quoted_from_strv(args); + expr = g_strdup_printf("(main '(\"%s\" \"--muhome=%s\" %s))", + mu_script_info_name(msi), + muhome, + mainargs ? mainargs : ""); - g_free (mainargs); + g_free(mainargs); argv[3] = g_strdup("-c"); argv[4] = expr; - scm_boot_guile (5, argv, guile_shell, NULL); + scm_boot_guile(5, argv, guile_shell, NULL); /* never reached but let's be correct(TM)*/ - g_strfreev (argv); + g_strfreev(argv); return TRUE; } -#else /*!BUILD_GUILE*/ +#else /*!BUILD_GUILE*/ gboolean -mu_script_guile_run (MuScriptInfo *msi, const char *muhome, - const char **args, GError **err) +mu_script_guile_run(MuScriptInfo* msi, const char* muhome, const char** args, GError** err) { - mu_util_g_set_error (err, MU_ERROR_INTERNAL, - "this mu does not have guile support"); + mu_util_g_set_error(err, MU_ERROR_INTERNAL, "this mu does not have guile support"); return FALSE; } #endif /*!BUILD_GUILE*/ diff --git a/lib/mu-script.hh b/lib/mu-script.hh index 349fc806..d3f7b1eb 100644 --- a/lib/mu-script.hh +++ b/lib/mu-script.hh @@ -33,8 +33,7 @@ struct MuScriptInfo; * * @return the name */ -const char* mu_script_info_name (MuScriptInfo *msi); - +const char* mu_script_info_name(MuScriptInfo* msi); /** * get the full filesystem path of the script @@ -43,7 +42,7 @@ const char* mu_script_info_name (MuScriptInfo *msi); * * @return the path */ -const char* mu_script_info_path (MuScriptInfo *msi); +const char* mu_script_info_path(MuScriptInfo* msi); /** * get a one-line description for the script @@ -52,7 +51,7 @@ const char* mu_script_info_path (MuScriptInfo *msi); * * @return the description, or NULL if there was none */ -const char* mu_script_info_one_line (MuScriptInfo *msi); +const char* mu_script_info_one_line(MuScriptInfo* msi); /** * get a full description for the script @@ -61,7 +60,7 @@ const char* mu_script_info_one_line (MuScriptInfo *msi); * * @return the description, or NULL if there was none */ -const char* mu_script_info_description (MuScriptInfo *msi); +const char* mu_script_info_description(MuScriptInfo* msi); /** * check whether either the name or one-line description of a @@ -73,8 +72,7 @@ const char* mu_script_info_description (MuScriptInfo *msi); * * @return TRUE if it matches, FALSE if not or in case of error */ -gboolean mu_script_info_matches_regex (MuScriptInfo *msi, const char *rxstr, - GError **err); +gboolean mu_script_info_matches_regex(MuScriptInfo* msi, const char* rxstr, GError** err); /** * Get the list of all scripts in path with extension ext @@ -87,16 +85,17 @@ gboolean mu_script_info_matches_regex (MuScriptInfo *msi, const char *rxstr, * * @return a list of Mu */ -GSList *mu_script_get_script_info_list (const char *path, const char *ext, - const char *descprefix, GError **err); +GSList* mu_script_get_script_info_list(const char* path, + const char* ext, + const char* descprefix, + GError** err); /** * destroy a list of MuScriptInfo* objects * * @param scriptslst a list of MuScriptInfo* objects */ -void mu_script_info_list_destroy (GSList *lst); - +void mu_script_info_list_destroy(GSList* lst); /** * find the MuScriptInfo object for the first script with a certain @@ -107,8 +106,7 @@ void mu_script_info_list_destroy (GSList *lst); * * @return a MuScriptInfo* object, or NULL if not found. */ -MuScriptInfo* mu_script_find_script_with_name (GSList *lst, const char *name); - +MuScriptInfo* mu_script_find_script_with_name(GSList* lst, const char* name); /** * run the guile script at path @@ -121,7 +119,7 @@ MuScriptInfo* mu_script_find_script_with_name (GSList *lst, const char *name); * @return FALSE in case of error -- otherwise, this function will * _not return_ */ -gboolean mu_script_guile_run (MuScriptInfo *msi, const char *muhome, - const char **args, GError **err); +gboolean +mu_script_guile_run(MuScriptInfo* msi, const char* muhome, const char** args, GError** err); #endif /*MU_SCRIPT_HH__*/ diff --git a/lib/mu-server.cc b/lib/mu-server.cc index d390dcbb..625de925 100644 --- a/lib/mu-server.cc +++ b/lib/mu-server.cc @@ -53,315 +53,346 @@ using namespace Command; /// @brief object to manage the server-context for all commands. struct Server::Private { - Private(Store& store, Output output): - store_{store}, - output_{output}, - command_map_{make_command_map()}, - query_{store_}, - keep_going_{true} {} - // - // construction helpers - // - CommandMap make_command_map(); + Private(Store& store, Output output) + : store_{store}, output_{output}, command_map_{make_command_map()}, query_{store_}, + keep_going_{true} + { + } + // + // construction helpers + // + CommandMap make_command_map(); - // - // acccessors - Store& store() { return store_; } - const Store& store() const { return store_; } - Indexer& indexer() { return store().indexer(); } - const CommandMap& command_map() const { return command_map_; } - const Query& query() const { return query_; } + // + // acccessors + Store& store() { return store_; } + const Store& store() const { return store_; } + Indexer& indexer() { return store().indexer(); } + const CommandMap& command_map() const { return command_map_; } + const Query& query() const { return query_; } - // - // invoke - // - bool invoke (const std::string& expr) noexcept; + // + // invoke + // + bool invoke(const std::string& expr) noexcept; - // - // output - // - void output_sexp(Sexp&& sexp) const { - if (output_) - output_(std::move(sexp)); - } - void output_sexp(Sexp::List&& lst) const { - output_sexp(Sexp::make_list(std::move(lst))); - } - size_t output_sexp (const QueryResults& qres); + // + // output + // + void output_sexp(Sexp&& sexp) const + { + if (output_) + output_(std::move(sexp)); + } + void output_sexp(Sexp::List&& lst) const { output_sexp(Sexp::make_list(std::move(lst))); } + size_t output_results(const QueryResults& qres, size_t batch_size) const; - // - // handlers for various commands. - // - void add_handler (const Parameters& params); - void compose_handler (const Parameters& params); - void contacts_handler (const Parameters& params); - void find_handler (const Parameters& params); - void help_handler (const Parameters& params); - void index_handler (const Parameters& params); - void move_handler (const Parameters& params); - void mkdir_handler (const Parameters& params); - void ping_handler (const Parameters& params); - void quit_handler (const Parameters& params); - void remove_handler (const Parameters& params); - void sent_handler (const Parameters& params); - void view_handler (const Parameters& params); + // + // handlers for various commands. + // + void add_handler(const Parameters& params); + void compose_handler(const Parameters& params); + void contacts_handler(const Parameters& params); + void find_handler(const Parameters& params); + void help_handler(const Parameters& params); + void index_handler(const Parameters& params); + void move_handler(const Parameters& params); + void mkdir_handler(const Parameters& params); + void ping_handler(const Parameters& params); + void quit_handler(const Parameters& params); + void remove_handler(const Parameters& params); + void sent_handler(const Parameters& params); + void view_handler(const Parameters& params); -private: - // helpers - Sexp build_message_sexp(MuMsg *msg, unsigned docid, - const Option qm, - MuMsgOptions opts); + private: + // helpers + Sexp build_message_sexp(MuMsg* msg, + unsigned docid, + const Option qm, + MuMsgOptions opts) const; - Sexp::List move_docid (Store::Id docid, const std::string& flagstr, - bool new_name, bool no_view); - Sexp::List perform_move (Store::Id docid, MuMsg *msg, - const std::string& maildirarg, - MuFlags flags, bool new_name, bool no_view); + Sexp::List + move_docid(Store::Id docid, const std::string& flagstr, bool new_name, bool no_view); + Sexp::List perform_move(Store::Id docid, + MuMsg* msg, + const std::string& maildirarg, + MuFlags flags, + bool new_name, + bool no_view); - bool maybe_mark_as_read (MuMsg *msg, Store::Id docid); - bool maybe_mark_msgid_as_read (const Mu::Query& query, const char* msgid); + bool maybe_mark_as_read(MuMsg* msg, Store::Id docid); + bool maybe_mark_msgid_as_read(const Mu::Query& query, const char* msgid); - Store& store_; - Server::Output output_; - const CommandMap command_map_; - const Query query_; + Store& store_; + Server::Output output_; + const CommandMap command_map_; + const Query query_; - std::atomic keep_going_{}; + std::atomic keep_going_{}; }; -static void -add_thread_info (Sexp::List& items, const QueryMatch& qmatch) +static Sexp +build_metadata(const QueryMatch& qmatch, unsigned docid) { - Sexp::List info; + Sexp::List mdata; - auto symbol_t = []{return Sexp::make_symbol("t");}; + auto symbol_t = [] { return Sexp::make_symbol("t"); }; - info.add_prop(":path", Sexp::make_string(qmatch.thread_path)); - info.add_prop(":level", Sexp::make_number(qmatch.thread_level)); - info.add_prop(":date", Sexp::make_string(qmatch.thread_date)); + mdata.add_prop(":docid", Sexp::make_number(docid)); + mdata.add_prop(":path", Sexp::make_string(qmatch.thread_path)); + mdata.add_prop(":level", Sexp::make_number(qmatch.thread_level)); + mdata.add_prop(":date", Sexp::make_string(qmatch.thread_date)); - Sexp::List dlist; - const auto td {::atoi(qmatch.thread_date.c_str())}; - dlist.add(Sexp::make_number((unsigned)(td >> 16))); - dlist.add(Sexp::make_number((unsigned)(td & 0xffff))); - dlist.add(Sexp::make_number(0)); - info.add_prop(":date-tstamp", Sexp::make_list(std::move(dlist))); + Sexp::List dlist; + const auto td{::atoi(qmatch.thread_date.c_str())}; + dlist.add(Sexp::make_number((unsigned)(td >> 16))); + dlist.add(Sexp::make_number((unsigned)(td & 0xffff))); + dlist.add(Sexp::make_number(0)); + mdata.add_prop(":date-tstamp", Sexp::make_list(std::move(dlist))); - if (qmatch.has_flag(QueryMatch::Flags::Root)) - info.add_prop(":root", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::Related)) - info.add_prop(":related", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::First)) - info.add_prop(":first-child", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::Last)) - info.add_prop(":last-child", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::Orphan)) - info.add_prop(":orphan", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::Duplicate)) - info.add_prop(":duplicate", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::HasChild)) - info.add_prop(":has-child", symbol_t()); - if (qmatch.has_flag(QueryMatch::Flags::ThreadSubject)) - info.add_prop(":thread-subject", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::Root)) + mdata.add_prop(":root", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::Related)) + mdata.add_prop(":related", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::First)) + mdata.add_prop(":first-child", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::Last)) + mdata.add_prop(":last-child", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::Orphan)) + mdata.add_prop(":orphan", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::Duplicate)) + mdata.add_prop(":duplicate", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::HasChild)) + mdata.add_prop(":has-child", symbol_t()); + if (qmatch.has_flag(QueryMatch::Flags::ThreadSubject)) + mdata.add_prop(":thread-subject", symbol_t()); - items.add_prop(":thread", Sexp::make_list(std::move(info))); + return Sexp::make_list(std::move(mdata)); } +/* a full message-sexp consists looks something like: + * (:meta () :message ()) + * + * before, we stuffed the meta-data in the message; however, + * keeping the message 'pristine' allows us to cache the message + * sexps (TBI). + */ Sexp -Server::Private::build_message_sexp (MuMsg *msg, unsigned docid, - const Option qm, - MuMsgOptions opts) +Server::Private::build_message_sexp(MuMsg* msg, + unsigned docid, + const Option qm, + MuMsgOptions opts) const { - auto lst{Mu::msg_to_sexp_list(msg, docid, opts)}; + Sexp::List msexp; - if (qm) - add_thread_info(lst, *qm); + msexp.add_prop(":message", Sexp::make_list(Mu::msg_to_sexp_list(msg, docid, opts))); + if (qm) + msexp.add_prop(":meta", build_metadata(*qm, docid)); - return Sexp::make_list(std::move(lst)); + return Sexp::make_list(std::move(msexp)); } + CommandMap -Server::Private::make_command_map () +Server::Private::make_command_map() { - CommandMap cmap; + CommandMap cmap; - using Type = Sexp::Type; + using Type = Sexp::Type; - cmap.emplace("add", - CommandInfo{ - ArgMap{ {":path", ArgInfo{Type::String, true, "file system path to the message" }}}, - "add a message to the store", - [&](const auto& params){add_handler(params);}}); + cmap.emplace( + "add", + CommandInfo{ + ArgMap{{":path", ArgInfo{Type::String, true, "file system path to the message"}}}, + "add a message to the store", + [&](const auto& params) { add_handler(params); }}); - cmap.emplace("compose", - CommandInfo{ - ArgMap{{":type", ArgInfo{Type::Symbol, true, - "type of composition: reply/forward/edit/resend/new"}}, - {":docid", ArgInfo{Type::Number, false, - "document id of parent-message, if any"}}, - {":decrypt", ArgInfo{Type::Symbol, false, - "whether to decrypt encrypted parts (if any)" }}}, - "compose a new message", - [&](const auto& params){compose_handler(params);}}); + cmap.emplace( + "compose", + CommandInfo{ + ArgMap{ + {":type", + ArgInfo{Type::Symbol, + true, + "type of composition: reply/forward/edit/resend/new"}}, + {":docid", + ArgInfo{Type::Number, false, "document id of parent-message, if any"}}, + {":decrypt", + ArgInfo{Type::Symbol, false, "whether to decrypt encrypted parts (if any)"}}}, + "compose a new message", + [&](const auto& params) { compose_handler(params); }}); - cmap.emplace("contacts", - CommandInfo{ - ArgMap{ {":personal", ArgInfo{Type::Symbol, false, - "only personal contacts" }}, - {":after", ArgInfo{Type::String, false, - "only contacts seen after time_t string" }}, - {":tstamp", ArgInfo{Type::String, false, - "return changes since tstamp" }}}, - "get contact information", - [&](const auto& params){contacts_handler(params);}}); - cmap.emplace("find", - CommandInfo{ - ArgMap{ {":query", ArgInfo{Type::String, true, "search expression" }}, - {":threads", ArgInfo{Type::Symbol, false, - "whether to include threading information" }}, - {":sortfield", ArgInfo{Type::Symbol, false, "the field to sort results by" }}, - {":descending", ArgInfo{Type::Symbol, false, - "whether to sort in descending order" }}, - {":maxnum", ArgInfo{Type::Number, false, - "maximum number of result (hint)" }}, - {":skip-dups", ArgInfo{Type::Symbol, false, - "whether to skip messages with duplicate message-ids" }}, - {":include-related", ArgInfo{Type::Symbol, false, - "whether to include other message related to matching ones" }}}, - "query the database for messages", - [&](const auto& params){find_handler(params);}}); + cmap.emplace( + "contacts", + CommandInfo{ + ArgMap{{":personal", ArgInfo{Type::Symbol, false, "only personal contacts"}}, + {":after", + ArgInfo{Type::String, false, "only contacts seen after time_t string"}}, + {":tstamp", ArgInfo{Type::String, false, "return changes since tstamp"}}}, + "get contact information", + [&](const auto& params) { contacts_handler(params); }}); + cmap.emplace( + "find", + CommandInfo{ + ArgMap{{":query", ArgInfo{Type::String, true, "search expression"}}, + {":threads", + ArgInfo{Type::Symbol, false, "whether to include threading information"}}, + {":sortfield", ArgInfo{Type::Symbol, false, "the field to sort results by"}}, + {":descending", + ArgInfo{Type::Symbol, false, "whether to sort in descending order"}}, + {":batch-size", ArgInfo{Type::Number, false, "batch size for result"}}, + {":maxnum", ArgInfo{Type::Number, false, "maximum number of result (hint)"}}, + {":skip-dups", + ArgInfo{Type::Symbol, + false, + "whether to skip messages with duplicate message-ids"}}, + {":include-related", + ArgInfo{Type::Symbol, + false, + "whether to include other message related to matching ones"}}}, + "query the database for messages", + [&](const auto& params) { find_handler(params); }}); - cmap.emplace("help", - CommandInfo{ - ArgMap{ {":command", ArgInfo{Type::Symbol, false, - "command to get information for" }}, - {":full", ArgInfo{Type::Symbol, false, - "show full descriptions" }}}, - "get information about one or all commands", - [&](const auto& params){help_handler(params);}}); - cmap.emplace("index", - CommandInfo{ - ArgMap{ {":my-addresses", ArgInfo{Type::List, false, "list of 'my' addresses"}}, - {":cleanup", ArgInfo{Type::Symbol, false, - "whether to remove stale messages from the store"}}, - {":lazy-check", ArgInfo{Type::Symbol, false, - "whether to avoid indexing up-to-date directories"}}}, - "scan maildir for new/updated/removed messages", - [&](const auto& params){index_handler(params);}}); + cmap.emplace( + "help", + CommandInfo{ + ArgMap{{":command", ArgInfo{Type::Symbol, false, "command to get information for"}}, + {":full", ArgInfo{Type::Symbol, false, "show full descriptions"}}}, + "get information about one or all commands", + [&](const auto& params) { help_handler(params); }}); + cmap.emplace( + "index", + CommandInfo{ + ArgMap{{":my-addresses", ArgInfo{Type::List, false, "list of 'my' addresses"}}, + {":cleanup", + ArgInfo{Type::Symbol, + false, + "whether to remove stale messages from the store"}}, + {":lazy-check", + ArgInfo{Type::Symbol, + false, + "whether to avoid indexing up-to-date directories"}}}, + "scan maildir for new/updated/removed messages", + [&](const auto& params) { index_handler(params); }}); - cmap.emplace("move", - CommandInfo{ - ArgMap{ {":docid", ArgInfo{Type::Number, false, "document-id"}}, - {":msgid", ArgInfo{Type::String, false, "message-id"}}, - {":flags", ArgInfo{Type::String, false, "new flags for the message"}}, - {":maildir", ArgInfo{Type::String, false, "the target maildir" }}, - {":rename", ArgInfo{Type::Symbol, false, "change filename when moving" }}, - {":no-view", ArgInfo{Type::Symbol, false, - "if set, do not hint at updating the view"}},}, - "move messages and/or change their flags", + cmap.emplace( + "move", + CommandInfo{ + ArgMap{ + {":docid", ArgInfo{Type::Number, false, "document-id"}}, + {":msgid", ArgInfo{Type::String, false, "message-id"}}, + {":flags", ArgInfo{Type::String, false, "new flags for the message"}}, + {":maildir", ArgInfo{Type::String, false, "the target maildir"}}, + {":rename", ArgInfo{Type::Symbol, false, "change filename when moving"}}, + {":no-view", + ArgInfo{Type::Symbol, false, "if set, do not hint at updating the view"}}, + }, + "move messages and/or change their flags", - [&](const auto& params){move_handler(params);}}); + [&](const auto& params) { move_handler(params); }}); - cmap.emplace("mkdir", - CommandInfo{ - ArgMap{ {":path", ArgInfo{Type::String, true, - "location for the new maildir" }}}, - "create a new maildir", - [&](const auto& params){mkdir_handler(params);}}); - cmap.emplace("ping", - CommandInfo{ - ArgMap{ {":queries", ArgInfo{Type::List, false, - "queries for which to get read/unread numbers"}}, - {":skip-dups", ArgInfo{Type::Symbol, false, - "whether to exclude messages with duplicate message-ids"}},}, - "ping the mu-server and get information in response", - [&](const auto& params){ping_handler(params);}}); + cmap.emplace( + "mkdir", + CommandInfo{ + ArgMap{{":path", ArgInfo{Type::String, true, "location for the new maildir"}}}, + "create a new maildir", + [&](const auto& params) { mkdir_handler(params); }}); + cmap.emplace( + "ping", + CommandInfo{ + ArgMap{ + {":queries", + ArgInfo{Type::List, false, "queries for which to get read/unread numbers"}}, + {":skip-dups", + ArgInfo{Type::Symbol, + false, + "whether to exclude messages with duplicate message-ids"}}, + }, + "ping the mu-server and get information in response", + [&](const auto& params) { ping_handler(params); }}); - cmap.emplace("quit", - CommandInfo{{}, - "quit the mu server", - [&](const auto& params){quit_handler(params);}}); + cmap.emplace("quit", CommandInfo{{}, "quit the mu server", [&](const auto& params) { + quit_handler(params); + }}); - cmap.emplace("remove", - CommandInfo{ - ArgMap{ {":docid", ArgInfo{Type::Number, true, - "document-id for the message to remove" }}}, - "remove a message from filesystem and database", - [&](const auto& params){remove_handler(params);}}); + cmap.emplace( + "remove", + CommandInfo{ + ArgMap{{":docid", + ArgInfo{Type::Number, true, "document-id for the message to remove"}}}, + "remove a message from filesystem and database", + [&](const auto& params) { remove_handler(params); }}); - cmap.emplace("sent", - CommandInfo{ - ArgMap{ {":path", ArgInfo{Type::String, true, - "path to the message file" }} - }, - "tell mu about a message that was sent", - [&](const auto& params){sent_handler(params);}}); + cmap.emplace( + "sent", + CommandInfo{ArgMap{{":path", ArgInfo{Type::String, true, "path to the message file"}}}, + "tell mu about a message that was sent", + [&](const auto& params) { sent_handler(params); }}); - cmap.emplace("view", - CommandInfo{ - ArgMap{{":docid", ArgInfo{Type::Number, false, "document-id"}}, - {":msgid", ArgInfo{Type::String, false, "message-id"}}, - {":path", ArgInfo{Type::String, false, "message filesystem path"}}, - {":mark-as-read", ArgInfo{Type::Symbol, false, - "mark message as read (if not already)"}}, - }, - "view a message. exactly one of docid/msgid/path must be specified", - [&](const auto& params){view_handler(params);}}); - return cmap; + cmap.emplace( + "view", + CommandInfo{ArgMap{ + {":docid", ArgInfo{Type::Number, false, "document-id"}}, + {":msgid", ArgInfo{Type::String, false, "message-id"}}, + {":path", ArgInfo{Type::String, false, "message filesystem path"}}, + {":mark-as-read", + ArgInfo{Type::Symbol, false, "mark message as read (if not already)"}}, + }, + "view a message. exactly one of docid/msgid/path must be specified", + [&](const auto& params) { view_handler(params); }}); + return cmap; } -G_GNUC_PRINTF(2,3) static Sexp -make_error (Error::Code errcode, const char* frm, ...) +G_GNUC_PRINTF(2, 3) static Sexp make_error(Error::Code errcode, const char* frm, ...) { - char *msg{}; - va_list ap; + char* msg{}; + va_list ap; - va_start (ap, frm); - g_vasprintf (&msg, frm, ap); - va_end (ap); + va_start(ap, frm); + g_vasprintf(&msg, frm, ap); + va_end(ap); - Sexp::List err; - err.add_prop(":error", Sexp::make_number(static_cast(errcode))); - err.add_prop(":message", Sexp::make_string(msg)); - g_free (msg); + Sexp::List err; + err.add_prop(":error", Sexp::make_number(static_cast(errcode))); + err.add_prop(":message", Sexp::make_string(msg)); + g_free(msg); - return Sexp::make_list(std::move(err)); + return Sexp::make_list(std::move(err)); } bool -Server::Private::invoke (const std::string& expr) noexcept +Server::Private::invoke(const std::string& expr) noexcept { - if (!keep_going_) - return false; + if (!keep_going_) + return false; - try { - auto call{Sexp::Sexp::make_parse(expr)}; - Command::invoke(command_map(), call); + try { + auto call{Sexp::Sexp::make_parse(expr)}; + Command::invoke(command_map(), call); - } catch (const Mu::Error& me) { - output_sexp(make_error(me.code(), "%s", me.what())); - } catch (const std::runtime_error& re) { - output_sexp(make_error(Error::Code::Internal, "caught exception: %s", re.what())); - keep_going_ = false; - } catch (...) { - output_sexp(make_error(Error::Code::Internal, "something went wrong: quiting")); - keep_going_ = false; - } + } catch (const Mu::Error& me) { + output_sexp(make_error(me.code(), "%s", me.what())); + } catch (const std::runtime_error& re) { + output_sexp(make_error(Error::Code::Internal, "caught exception: %s", re.what())); + keep_going_ = false; + } catch (...) { + output_sexp(make_error(Error::Code::Internal, "something went wrong: quiting")); + keep_going_ = false; + } - return keep_going_; + return keep_going_; } - static MuMsgOptions -message_options (const Parameters& params) +message_options(const Parameters& params) { - const auto decrypt{get_bool_or(params, ":decrypt", false)}; + const auto decrypt{get_bool_or(params, ":decrypt", false)}; - int opts{MU_MSG_OPTION_NONE}; + int opts{MU_MSG_OPTION_NONE}; - if (decrypt) - opts |= MU_MSG_OPTION_DECRYPT | MU_MSG_OPTION_USE_AGENT; + if (decrypt) + opts |= MU_MSG_OPTION_DECRYPT | MU_MSG_OPTION_USE_AGENT; - return (MuMsgOptions)opts; + return (MuMsgOptions)opts; } /* 'add' adds a message to the database, and takes two parameters: 'path', which @@ -370,57 +401,57 @@ message_options (const Parameters& params) * information about the newly added message (details: see code below) */ void -Server::Private::add_handler (const Parameters& params) +Server::Private::add_handler(const Parameters& params) { - auto path{get_string_or(params, ":path")}; - const auto docid{store().add_message(path)}; + auto path{get_string_or(params, ":path")}; + const auto docid{store().add_message(path)}; - Sexp::List expr; - expr.add_prop(":info", Sexp::make_symbol("add")); - expr.add_prop(":path", Sexp::make_string(path)); - expr.add_prop(":docid", Sexp::make_number(docid)); + Sexp::List expr; + expr.add_prop(":info", Sexp::make_symbol("add")); + expr.add_prop(":path", Sexp::make_string(path)); + expr.add_prop(":docid", Sexp::make_number(docid)); - output_sexp(Sexp::make_list(std::move(expr))); + output_sexp(Sexp::make_list(std::move(expr))); - auto msg{store().find_message(docid)}; - if (!msg) - throw Error(Error::Code::Store, - "failed to get message at %s (docid=%u)", - path.c_str(), docid); + auto msg{store().find_message(docid)}; + if (!msg) + throw Error(Error::Code::Store, + "failed to get message at %s (docid=%u)", + path.c_str(), + docid); - Sexp::List update; - update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_VERIFY)); - output_sexp(Sexp::make_list(std::move(update))); - mu_msg_unref(msg); + Sexp::List update; + update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_VERIFY)); + output_sexp(Sexp::make_list(std::move(update))); + mu_msg_unref(msg); } - struct PartInfo { - Sexp::List attseq; - MuMsgOptions opts; + Sexp::List attseq; + MuMsgOptions opts; }; static void -each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) +each_part(MuMsg* msg, MuMsgPart* part, PartInfo* pinfo) { - /* exclude things that don't look like proper attachments, unless they're images */ - if (!mu_msg_part_maybe_attachment(part)) - return; + /* exclude things that don't look like proper attachments, unless they're images */ + if (!mu_msg_part_maybe_attachment(part)) + return; - GError *gerr{}; - char *cachefile = mu_msg_part_save_temp ( - msg, (MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE), - part->index, &gerr); - if (!cachefile) - throw Error (Error::Code::File, &gerr, "failed to save part"); + GError* gerr{}; + char* cachefile = + mu_msg_part_save_temp(msg, + (MuMsgOptions)(pinfo->opts | MU_MSG_OPTION_OVERWRITE), + part->index, + &gerr); + if (!cachefile) + throw Error(Error::Code::File, &gerr, "failed to save part"); - Sexp::List pi; - pi.add_prop(":file-name", Sexp::make_string(cachefile)); - pi.add_prop(":mime-type", Sexp::make_string(format("%s/%s", - part->type, - part->subtype))); - pinfo->attseq.add(Sexp::make_list(std::move(pi))); - g_free (cachefile); + Sexp::List pi; + pi.add_prop(":file-name", Sexp::make_string(cachefile)); + pi.add_prop(":mime-type", Sexp::make_string(format("%s/%s", part->type, part->subtype))); + pinfo->attseq.add(Sexp::make_list(std::move(pi))); + g_free(cachefile); } /* 'compose' produces the un-changed *original* message sexp (ie., the message @@ -435,113 +466,113 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) * Note ':include' t or nil determines whether to include attachments */ void -Server::Private::compose_handler (const Parameters& params) +Server::Private::compose_handler(const Parameters& params) { - const auto ctype{get_symbol_or(params, ":type")}; + const auto ctype{get_symbol_or(params, ":type")}; - Sexp::List comp_lst; - comp_lst.add_prop(":compose", Sexp::make_symbol(std::string(ctype))); + Sexp::List comp_lst; + comp_lst.add_prop(":compose", Sexp::make_symbol(std::string(ctype))); - if (ctype == "reply" || ctype == "forward" || ctype == "edit" || ctype == "resend") { + if (ctype == "reply" || ctype == "forward" || ctype == "edit" || ctype == "resend") { + GError* gerr{}; + const unsigned docid{(unsigned)get_int_or(params, ":docid")}; + auto msg{store().find_message(docid)}; + if (!msg) + throw Error{Error::Code::Store, &gerr, "failed to get message %u", docid}; - GError *gerr{}; - const unsigned docid{(unsigned)get_int_or(params, ":docid")}; - auto msg{store().find_message(docid)}; - if (!msg) - throw Error{Error::Code::Store, &gerr, "failed to get message %u", docid}; + const auto opts{message_options(params)}; + comp_lst.add_prop(":original", build_message_sexp(msg, docid, {}, opts)); - const auto opts{message_options(params)}; - comp_lst.add_prop(":original", build_message_sexp(msg, docid, {}, opts)); + if (ctype == "forward") { + PartInfo pinfo{}; + pinfo.opts = opts; + mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo); + if (!pinfo.attseq.empty()) + comp_lst.add_prop(":include", + Sexp::make_list(std::move(pinfo.attseq))); + } + mu_msg_unref(msg); - if (ctype == "forward") { - PartInfo pinfo{}; - pinfo.opts = opts; - mu_msg_part_foreach (msg, opts, - (MuMsgPartForeachFunc)each_part, &pinfo); - if (!pinfo.attseq.empty()) - comp_lst.add_prop (":include", - Sexp::make_list(std::move(pinfo.attseq))); - } - mu_msg_unref (msg); + } else if (ctype != "new") + throw Error(Error::Code::InvalidArgument, + "invalid compose type '%s'", + ctype.c_str()); - } else if (ctype != "new") - throw Error(Error::Code::InvalidArgument, "invalid compose type '%s'", - ctype.c_str()); - - output_sexp (std::move(comp_lst)); + output_sexp(std::move(comp_lst)); } void -Server::Private::contacts_handler (const Parameters& params) +Server::Private::contacts_handler(const Parameters& params) { - const auto personal = get_bool_or(params, ":personal"); - const auto afterstr = get_string_or(params, ":after"); - const auto tstampstr = get_string_or(params, ":tstamp"); + const auto personal = get_bool_or(params, ":personal"); + const auto afterstr = get_string_or(params, ":after"); + const auto tstampstr = get_string_or(params, ":tstamp"); - const auto after{afterstr.empty() ? 0 : - g_ascii_strtoll(date_to_time_t_string(afterstr, true).c_str(), {}, 10)}; - const auto tstamp = g_ascii_strtoll (tstampstr.c_str(), NULL, 10); + const auto after{ + afterstr.empty() + ? 0 + : g_ascii_strtoll(date_to_time_t_string(afterstr, true).c_str(), {}, 10)}; + const auto tstamp = g_ascii_strtoll(tstampstr.c_str(), NULL, 10); - auto rank{0}; - Sexp::List contacts; - store().contacts().for_each([&](const ContactInfo& ci) { + auto rank{0}; + Sexp::List contacts; + store().contacts().for_each([&](const ContactInfo& ci) { + rank++; - rank++; + /* since the last time we got some contacts */ + if (tstamp > ci.tstamp) + return; + /* (maybe) only include 'personal' contacts */ + if (personal && !ci.personal) + return; + /* only include newer-than-x contacts */ + if (after > ci.last_seen) + return; - /* since the last time we got some contacts */ - if (tstamp > ci.tstamp) - return; - /* (maybe) only include 'personal' contacts */ - if (personal && !ci.personal) - return; - /* only include newer-than-x contacts */ - if (after > ci.last_seen) - return; + Sexp::List contact; + contact.add_prop(":address", Sexp::make_string(ci.full_address)); + contact.add_prop(":rank", Sexp::make_number(rank)); - Sexp::List contact; - contact.add_prop(":address", Sexp::make_string(ci.full_address)); - contact.add_prop(":rank", Sexp::make_number(rank)); + contacts.add(Sexp::make_list(std::move(contact))); + }); - contacts.add(Sexp::make_list(std::move(contact))); - }); - - Sexp::List seq; - seq.add_prop(":contacts", Sexp::make_list(std::move(contacts))); - seq.add_prop(":tstamp", Sexp::make_string(format("%" G_GINT64_FORMAT, - g_get_monotonic_time()))); - /* dump the contacts cache as a giant sexp */ - output_sexp(std::move(seq)); + Sexp::List seq; + seq.add_prop(":contacts", Sexp::make_list(std::move(contacts))); + seq.add_prop(":tstamp", + Sexp::make_string(format("%" G_GINT64_FORMAT, g_get_monotonic_time()))); + /* dump the contacts cache as a giant sexp */ + output_sexp(std::move(seq)); } /* get a *list* of all messages with the given message id */ static std::vector -docids_for_msgid (const Query& q, const std::string& msgid, size_t max=100) +docids_for_msgid(const Query& q, const std::string& msgid, size_t max = 100) { - if (msgid.size() > Store::MaxTermLength) { - throw Error(Error::Code::InvalidArgument, - "invalid message-id '%s'", msgid.c_str()); - } + if (msgid.size() > Store::MaxTermLength) { + throw Error(Error::Code::InvalidArgument, "invalid message-id '%s'", msgid.c_str()); + } - const auto xprefix{mu_msg_field_shortcut(MU_MSG_FIELD_ID_MSGID)}; - /*XXX this is a bit dodgy */ - auto tmp{g_ascii_strdown(msgid.c_str(), -1)}; - auto expr{g_strdup_printf("%c:%s", xprefix, tmp)}; - g_free(tmp); + const auto xprefix{mu_msg_field_shortcut(MU_MSG_FIELD_ID_MSGID)}; + /*XXX this is a bit dodgy */ + auto tmp{g_ascii_strdown(msgid.c_str(), -1)}; + auto expr{g_strdup_printf("%c:%s", xprefix, tmp)}; + g_free(tmp); - GError *gerr{}; - const auto res{q.run(expr, MU_MSG_FIELD_ID_NONE, QueryFlags::None, max)}; - g_free (expr); - if (!res) - throw Error(Error::Code::Store, &gerr, "failed to run msgid-query"); - else if (res->empty()) - throw Error(Error::Code::NotFound, - "could not find message(s) for msgid %s", msgid.c_str()); + GError* gerr{}; + const auto res{q.run(expr, MU_MSG_FIELD_ID_NONE, QueryFlags::None, max)}; + g_free(expr); + if (!res) + throw Error(Error::Code::Store, &gerr, "failed to run msgid-query"); + else if (res->empty()) + throw Error(Error::Code::NotFound, + "could not find message(s) for msgid %s", + msgid.c_str()); - std::vector docids{}; - for(auto&& mi: *res) - docids.emplace_back(mi.doc_id()); + std::vector docids{}; + for (auto&& mi : *res) + docids.emplace_back(mi.doc_id()); - return docids; + return docids; } /* @@ -549,284 +580,293 @@ docids_for_msgid (const Query& q, const std::string& msgid, size_t max=100) * mu_store_get_path could be added if this turns out to be a problem */ static std::string -path_from_docid (const Store& store, unsigned docid) +path_from_docid(const Store& store, unsigned docid) { - auto msg{store.find_message(docid)}; - if (!msg) - throw Error(Error::Code::Store, "could not get message from store"); + auto msg{store.find_message(docid)}; + if (!msg) + throw Error(Error::Code::Store, "could not get message from store"); - auto p{mu_msg_get_path(msg)}; - if (!p) { - mu_msg_unref(msg); - throw Error(Error::Code::Store, - "could not get path for message %u", docid); - } + auto p{mu_msg_get_path(msg)}; + if (!p) { + mu_msg_unref(msg); + throw Error(Error::Code::Store, "could not get path for message %u", docid); + } - std::string msgpath{p}; - mu_msg_unref (msg); + std::string msgpath{p}; + mu_msg_unref(msg); - return msgpath; + return msgpath; } - static std::vector -determine_docids (const Query& q, const Parameters& params) +determine_docids(const Query& q, const Parameters& params) { - auto docid{get_int_or(params, ":docid", 0)}; - const auto msgid{get_string_or(params, ":msgid")}; + auto docid{get_int_or(params, ":docid", 0)}; + const auto msgid{get_string_or(params, ":msgid")}; - if ((docid == 0) == msgid.empty()) - throw Error(Error::Code::InvalidArgument, - "precisely one of docid and msgid must be specified"); + if ((docid == 0) == msgid.empty()) + throw Error(Error::Code::InvalidArgument, + "precisely one of docid and msgid must be specified"); - if (docid != 0) - return { (unsigned)docid }; - else - return docids_for_msgid (q, msgid.c_str()); + if (docid != 0) + return {(unsigned)docid}; + else + return docids_for_msgid(q, msgid.c_str()); } - size_t -Server::Private::output_sexp (const QueryResults& qres) +Server::Private::output_results(const QueryResults& qres, size_t batch_size) const { - size_t n{}; - for (auto&& mi: qres) { - ++n; - auto msg{mi.floating_msg()}; - if (!msg) - continue; + size_t n{}; - auto qm{mi.query_match()}; - output_sexp(build_message_sexp(msg, mi.doc_id(), - qm, MU_MSG_OPTION_HEADERS_ONLY)); - } + for (auto&& mi : qres) { + auto msg{mi.floating_msg()}; + if (!msg) + continue; + ++n; + auto qm{mi.query_match()}; + Sexp::List lst; + lst.add_prop(":header", + build_message_sexp(msg, mi.doc_id(), qm, MU_MSG_OPTION_HEADERS_ONLY)); + output_sexp(std::move(lst)); + } - return n; -} - - -void -Server::Private::find_handler (const Parameters& params) -{ - const auto q{get_string_or(params, ":query")}; - const auto threads{get_bool_or(params, ":threads", false)}; - const auto sortfieldstr{get_symbol_or(params, ":sortfield", "")}; - const auto descending{get_bool_or(params, ":descending", false)}; - const auto maxnum{get_int_or(params, ":maxnum", -1/*unlimited*/)}; - const auto skip_dups{get_bool_or(params, ":skip-dups", false)}; - const auto include_related{get_bool_or(params, ":include-related", false)}; - - MuMsgFieldId sort_field{MU_MSG_FIELD_ID_NONE}; - if (!sortfieldstr.empty()) { - sort_field = mu_msg_field_id_from_name ( - sortfieldstr.c_str() + 1, FALSE); // skip ':' - if (sort_field == MU_MSG_FIELD_ID_NONE) - throw Error{Error::Code::InvalidArgument, "invalid sort field %s", - sortfieldstr.c_str()}; - } - - auto qflags{QueryFlags::None}; - if (descending) - qflags |= QueryFlags::Descending; - if (skip_dups) - qflags |= QueryFlags::SkipDuplicates; - if (include_related) - qflags |= QueryFlags::IncludeRelated; - if (threads) - qflags |= QueryFlags::Threading; - - auto qres{query().run(q, sort_field, qflags, maxnum)}; - if (!qres) - throw Error(Error::Code::Query, "failed to run query"); - - /* before sending new results, send an 'erase' message, so the frontend - * knows it should erase the headers buffer. this will ensure that the - * output of two finds will not be mixed. */ - { - Sexp::List lst; - lst.add_prop(":erase", Sexp::make_symbol("t")); - output_sexp(std::move(lst)); - } - - { - const auto foundnum{output_sexp (*qres)}; - Sexp::List lst; - lst.add_prop(":found", Sexp::make_number(foundnum)); - output_sexp(std::move(lst)); - } + return n; } void -Server::Private::help_handler (const Parameters& params) +Server::Private::find_handler(const Parameters& params) { - const auto command{get_symbol_or(params, ":command", "")}; - const auto full{get_bool_or(params, ":full", !command.empty())}; + const auto q{get_string_or(params, ":query")}; + const auto threads{get_bool_or(params, ":threads", false)}; + const auto batch_size{get_int_or(params, ":batch-size", 60)}; + const auto sortfieldstr{get_symbol_or(params, ":sortfield", "")}; + const auto descending{get_bool_or(params, ":descending", false)}; + const auto maxnum{get_int_or(params, ":maxnum", -1 /*unlimited*/)}; + const auto skip_dups{get_bool_or(params, ":skip-dups", false)}; + const auto include_related{get_bool_or(params, ":include-related", false)}; - if (command.empty()) { - std::cout << ";; Commands are s-expressions of the form\n" - << ";; ( :param1 val1 :param2 val2 ...)\n" - << ";; For instance:\n;; (help :command quit)\n" - << ";; to get detailed information about the 'quit'\n;;\n"; - std::cout << ";; The following commands are available:\n\n"; - } + MuMsgFieldId sort_field{MU_MSG_FIELD_ID_NONE}; + if (!sortfieldstr.empty()) { + sort_field = mu_msg_field_id_from_name(sortfieldstr.c_str() + 1, FALSE); // skip ':' + if (sort_field == MU_MSG_FIELD_ID_NONE) + throw Error{Error::Code::InvalidArgument, + "invalid sort field %s", + sortfieldstr.c_str()}; + } + if (batch_size < 1) + throw Error{Error::Code::InvalidArgument, "invalid batch-size %d", batch_size}; - std::vector names; - for (auto&& name_cmd: command_map()) - names.emplace_back(name_cmd.first); - std::sort(names.begin(), names.end()); + auto qflags{QueryFlags::None}; + if (descending) + qflags |= QueryFlags::Descending; + if (skip_dups) + qflags |= QueryFlags::SkipDuplicates; + if (include_related) + qflags |= QueryFlags::IncludeRelated; + if (threads) + qflags |= QueryFlags::Threading; - for (auto&& name: names) { - const auto& info{command_map().find(name)->second}; + auto qres{query().run(q, sort_field, qflags, maxnum)}; + if (!qres) + throw Error(Error::Code::Query, "failed to run query"); - if (!command.empty() && name != command) - continue; + /* before sending new results, send an 'erase' message, so the frontend + * knows it should erase the headers buffer. this will ensure that the + * output of two finds will not be mixed. */ + { + Sexp::List lst; + lst.add_prop(":erase", Sexp::make_symbol("t")); + output_sexp(std::move(lst)); + } - if (!command.empty()) - std::cout << ";; " << format("%-10s -- %s\n", name.c_str(), - info.docstring.c_str()); - else - std::cout << ";; " << name.c_str() << " -- " - << info.docstring.c_str() << '\n'; - if (!full) - continue; + const auto foundnum{output_results(*qres, static_cast(batch_size))}; - for (auto&& argname: info.sorted_argnames()) { - const auto& arg{info.args.find(argname)}; - std::cout << ";; " - << format("%-17s : %-24s ", arg->first.c_str(), - to_string(arg->second).c_str()); - std::cout << " " << arg->second.docstring << "\n"; - } - std::cout << ";;\n"; - } + { + Sexp::List lst; + lst.add_prop(":found", Sexp::make_number(foundnum)); + output_sexp(std::move(lst)); + } +} + +void +Server::Private::help_handler(const Parameters& params) +{ + const auto command{get_symbol_or(params, ":command", "")}; + const auto full{get_bool_or(params, ":full", !command.empty())}; + + if (command.empty()) { + std::cout << ";; Commands are s-expressions of the form\n" + << ";; ( :param1 val1 :param2 val2 ...)\n" + << ";; For instance:\n;; (help :command quit)\n" + << ";; to get detailed information about the 'quit'\n;;\n"; + std::cout << ";; The following commands are available:\n\n"; + } + + std::vector names; + for (auto&& name_cmd : command_map()) + names.emplace_back(name_cmd.first); + std::sort(names.begin(), names.end()); + + for (auto&& name : names) { + const auto& info{command_map().find(name)->second}; + + if (!command.empty() && name != command) + continue; + + if (!command.empty()) + std::cout << ";; " + << format("%-10s -- %s\n", name.c_str(), info.docstring.c_str()); + else + std::cout << ";; " << name.c_str() << " -- " << info.docstring.c_str() + << '\n'; + if (!full) + continue; + + for (auto&& argname : info.sorted_argnames()) { + const auto& arg{info.args.find(argname)}; + std::cout << ";; " + << format("%-17s : %-24s ", + arg->first.c_str(), + to_string(arg->second).c_str()); + std::cout << " " << arg->second.docstring << "\n"; + } + std::cout << ";;\n"; + } } static Sexp::List -get_stats (const Indexer::Progress& stats, const std::string& state) +get_stats(const Indexer::Progress& stats, const std::string& state) { - Sexp::List lst; + Sexp::List lst; - lst.add_prop(":info", Sexp::make_symbol("index")); - lst.add_prop(":status", Sexp::make_symbol(std::string{state})); - lst.add_prop(":processed", Sexp::make_number(stats.processed)); - lst.add_prop(":updated", Sexp::make_number(stats.updated)); - lst.add_prop(":cleaned-up", Sexp::make_number(stats.removed)); + lst.add_prop(":info", Sexp::make_symbol("index")); + lst.add_prop(":status", Sexp::make_symbol(std::string{state})); + lst.add_prop(":processed", Sexp::make_number(stats.processed)); + lst.add_prop(":updated", Sexp::make_number(stats.updated)); + lst.add_prop(":cleaned-up", Sexp::make_number(stats.removed)); - return lst; + return lst; } void -Server::Private::index_handler (const Parameters& params) +Server::Private::index_handler(const Parameters& params) { - Mu::Indexer::Config conf{}; - conf.cleanup = get_bool_or(params, ":cleanup"); - conf.lazy_check = get_bool_or(params, ":lazy-check"); + Mu::Indexer::Config conf{}; + conf.cleanup = get_bool_or(params, ":cleanup"); + conf.lazy_check = get_bool_or(params, ":lazy-check"); - indexer().stop(); + indexer().stop(); - indexer().start(conf); - while (indexer().is_running()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - output_sexp(get_stats(indexer().progress(), "running")); - } - output_sexp(get_stats(indexer().progress(), "complete")); + indexer().start(conf); + while (indexer().is_running()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + output_sexp(get_stats(indexer().progress(), "running")); + } + output_sexp(get_stats(indexer().progress(), "complete")); } void -Server::Private::mkdir_handler (const Parameters& params) +Server::Private::mkdir_handler(const Parameters& params) { - const auto path{get_string_or(params, ":path")}; + const auto path{get_string_or(params, ":path")}; - GError *gerr{}; - if (!mu_maildir_mkdir(path.c_str(), 0755, FALSE, &gerr)) - throw Error{Error::Code::File, &gerr, "failed to create maildir"}; + GError* gerr{}; + if (!mu_maildir_mkdir(path.c_str(), 0755, FALSE, &gerr)) + throw Error{Error::Code::File, &gerr, "failed to create maildir"}; - Sexp::List lst; - lst.add_prop(":info", Sexp::make_string("mkdir")); - lst.add_prop(":message", Sexp::make_string(format("%s has been created", - path.c_str()))); + Sexp::List lst; + lst.add_prop(":info", Sexp::make_string("mkdir")); + lst.add_prop(":message", Sexp::make_string(format("%s has been created", path.c_str()))); - output_sexp(std::move(lst)); + output_sexp(std::move(lst)); } - static MuFlags -get_flags (const std::string& path, const std::string& flagstr) +get_flags(const std::string& path, const std::string& flagstr) { - if (flagstr.empty()) - return MU_FLAG_NONE; /* ie., ignore flags */ - else { - /* if there's a '+' or '-' sign in the string, it must - * be a flag-delta */ - if (strstr (flagstr.c_str(), "+") || strstr (flagstr.c_str(), "-")) { - auto oldflags = mu_maildir_get_flags_from_path (path.c_str()); - return mu_flags_from_str_delta (flagstr.c_str(), oldflags, MU_FLAG_TYPE_ANY); - } else - return mu_flags_from_str (flagstr.c_str(), MU_FLAG_TYPE_ANY, - TRUE /*ignore invalid*/); - } + if (flagstr.empty()) + return MU_FLAG_NONE; /* ie., ignore flags */ + else { + /* if there's a '+' or '-' sign in the string, it must + * be a flag-delta */ + if (strstr(flagstr.c_str(), "+") || strstr(flagstr.c_str(), "-")) { + auto oldflags = mu_maildir_get_flags_from_path(path.c_str()); + return mu_flags_from_str_delta(flagstr.c_str(), oldflags, MU_FLAG_TYPE_ANY); + } else + return mu_flags_from_str(flagstr.c_str(), + MU_FLAG_TYPE_ANY, + TRUE /*ignore invalid*/); + } } Sexp::List -Server::Private::perform_move (Store::Id docid, MuMsg *msg, const std::string& maildirarg, - MuFlags flags, bool new_name, bool no_view) +Server::Private::perform_move(Store::Id docid, + MuMsg* msg, + const std::string& maildirarg, + MuFlags flags, + bool new_name, + bool no_view) { - bool different_mdir{}; - auto maildir{maildirarg}; - if (maildir.empty()) { - maildir = mu_msg_get_maildir (msg); - different_mdir = false; - } else /* are we moving to a different mdir, or is it just flags? */ - different_mdir = maildir != mu_msg_get_maildir(msg); + bool different_mdir{}; + auto maildir{maildirarg}; + if (maildir.empty()) { + maildir = mu_msg_get_maildir(msg); + different_mdir = false; + } else /* are we moving to a different mdir, or is it just flags? */ + different_mdir = maildir != mu_msg_get_maildir(msg); - GError* gerr{}; - if (!mu_msg_move_to_maildir (msg, maildir.c_str(), flags, TRUE, new_name, &gerr)) - throw Error{Error::Code::File, &gerr, "failed to move message"}; + GError* gerr{}; + if (!mu_msg_move_to_maildir(msg, maildir.c_str(), flags, TRUE, new_name, &gerr)) + throw Error{Error::Code::File, &gerr, "failed to move message"}; - /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir fields - * will be updated as wel */ - if (!store_.update_message (msg, docid)) - throw Error{Error::Code::Store, "failed to store updated message"}; + /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir fields + * will be updated as wel */ + if (!store_.update_message(msg, docid)) + throw Error{Error::Code::Store, "failed to store updated message"}; - Sexp::List seq; - seq.add_prop(":update", build_message_sexp (msg, docid, {}, MU_MSG_OPTION_VERIFY)); - /* note, the :move t thing is a hint to the frontend that it - * could remove the particular header */ - if (different_mdir) - seq.add_prop(":move", Sexp::make_symbol("t")); - if (!no_view) - seq.add_prop(":maybe-view", Sexp::make_symbol("t")); + Sexp::List seq; + seq.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_VERIFY)); + /* note, the :move t thing is a hint to the frontend that it + * could remove the particular header */ + if (different_mdir) + seq.add_prop(":move", Sexp::make_symbol("t")); + if (!no_view) + seq.add_prop(":maybe-view", Sexp::make_symbol("t")); - return seq; + return seq; } Sexp::List -Server::Private::move_docid (Store::Id docid, const std::string& flagstr, - bool new_name, bool no_view) +Server::Private::move_docid(Store::Id docid, + const std::string& flagstr, + bool new_name, + bool no_view) { - if (docid == Store::InvalidId) - throw Error{Error::Code::InvalidArgument, "invalid docid"}; + if (docid == Store::InvalidId) + throw Error{Error::Code::InvalidArgument, "invalid docid"}; - auto msg{store_.find_message(docid)}; - try { - if (!msg) - throw Error{Error::Code::Store, "failed to get message from store"}; + auto msg{store_.find_message(docid)}; + try { + if (!msg) + throw Error{Error::Code::Store, "failed to get message from store"}; - const auto flags = flagstr.empty() ? mu_msg_get_flags (msg) : - get_flags (mu_msg_get_path(msg), flagstr); - if (flags == MU_FLAG_INVALID) - throw Error{Error::Code::InvalidArgument, "invalid flags '%s'", - flagstr.c_str()}; + const auto flags = flagstr.empty() ? mu_msg_get_flags(msg) + : get_flags(mu_msg_get_path(msg), flagstr); + if (flags == MU_FLAG_INVALID) + throw Error{Error::Code::InvalidArgument, + "invalid flags '%s'", + flagstr.c_str()}; - auto lst = perform_move(docid, msg, "", flags, new_name, no_view); - mu_msg_unref (msg); - return lst; + auto lst = perform_move(docid, msg, "", flags, new_name, no_view); + mu_msg_unref(msg); + return lst; - } catch (...) { - if (msg) - mu_msg_unref (msg); - throw; - } + } catch (...) { + if (msg) + mu_msg_unref(msg); + throw; + } } /* @@ -839,253 +879,244 @@ Server::Private::move_docid (Store::Id docid, const std::string& flagstr, * */ void -Server::Private::move_handler (const Parameters& params) +Server::Private::move_handler(const Parameters& params) { - auto maildir{get_string_or(params, ":maildir")}; - const auto flagstr{get_string_or(params, ":flags")}; - const auto rename{get_bool_or (params, ":rename")}; - const auto no_view{get_bool_or (params, ":noupdate")}; - const auto docids{determine_docids (query(), params)}; + auto maildir{get_string_or(params, ":maildir")}; + const auto flagstr{get_string_or(params, ":flags")}; + const auto rename{get_bool_or(params, ":rename")}; + const auto no_view{get_bool_or(params, ":noupdate")}; + const auto docids{determine_docids(query(), params)}; - if (docids.size() > 1) { - if (!maildir.empty()) // ie. duplicate message-ids. - throw Mu::Error{Error::Code::Store, - "can't move multiple messages at the same time"}; - // multi. - for (auto&& docid: docids) - output_sexp(move_docid(docid, flagstr, rename, no_view)); - return; - } - auto docid{docids.at(0)}; + if (docids.size() > 1) { + if (!maildir.empty()) // ie. duplicate message-ids. + throw Mu::Error{Error::Code::Store, + "can't move multiple messages at the same time"}; + // multi. + for (auto&& docid : docids) + output_sexp(move_docid(docid, flagstr, rename, no_view)); + return; + } + auto docid{docids.at(0)}; - GError *gerr{}; - auto msg{store().find_message(docid)}; - if (!msg) - throw Error{Error::Code::InvalidArgument, &gerr, - "could not create message"}; + GError* gerr{}; + auto msg{store().find_message(docid)}; + if (!msg) + throw Error{Error::Code::InvalidArgument, &gerr, "could not create message"}; - /* if maildir was not specified, take the current one */ - if (maildir.empty()) - maildir = mu_msg_get_maildir (msg); + /* if maildir was not specified, take the current one */ + if (maildir.empty()) + maildir = mu_msg_get_maildir(msg); - /* determine the real target flags, which come from the flags-parameter - * we received (ie., flagstr), if any, plus the existing message - * flags. */ - MuFlags flags{}; - if (!flagstr.empty()) - flags = get_flags (mu_msg_get_path(msg), flagstr.c_str()); - else - flags = mu_msg_get_flags (msg); + /* determine the real target flags, which come from the flags-parameter + * we received (ie., flagstr), if any, plus the existing message + * flags. */ + MuFlags flags{}; + if (!flagstr.empty()) + flags = get_flags(mu_msg_get_path(msg), flagstr.c_str()); + else + flags = mu_msg_get_flags(msg); - if (flags == MU_FLAG_INVALID) { - mu_msg_unref(msg); - throw Error{Error::Code::InvalidArgument, "invalid flags"}; - } + if (flags == MU_FLAG_INVALID) { + mu_msg_unref(msg); + throw Error{Error::Code::InvalidArgument, "invalid flags"}; + } - try { - output_sexp(perform_move(docid, msg, maildir, flags, - rename, no_view)); - } catch (...) { - mu_msg_unref(msg); - throw; - } + try { + output_sexp(perform_move(docid, msg, maildir, flags, rename, no_view)); + } catch (...) { + mu_msg_unref(msg); + throw; + } - mu_msg_unref(msg); + mu_msg_unref(msg); } void -Server::Private::ping_handler (const Parameters& params) +Server::Private::ping_handler(const Parameters& params) { - const auto storecount{store().size()}; - if (storecount == (unsigned)-1) - throw Error{Error::Code::Store, "failed to read store"}; + const auto storecount{store().size()}; + if (storecount == (unsigned)-1) + throw Error{Error::Code::Store, "failed to read store"}; - const auto queries = get_string_vec (params, ":queries"); - Sexp::List qresults; - for (auto&& q: queries) { + const auto queries = get_string_vec(params, ":queries"); + Sexp::List qresults; + for (auto&& q : queries) { + const auto count{query().count(q)}; + const auto unreadq{format("flag:unread AND (%s)", q.c_str())}; + const auto unread{query().count(unreadq)}; - const auto count{query().count(q)}; - const auto unreadq{format("flag:unread AND (%s)", q.c_str())}; - const auto unread{query().count(unreadq)}; + Sexp::List lst; + lst.add_prop(":query", Sexp::make_string(q)); + lst.add_prop(":count", Sexp::make_number(count)); + lst.add_prop(":unread", Sexp::make_number(unread)); - Sexp::List lst; - lst.add_prop(":query", Sexp::make_string(q)); - lst.add_prop(":count", Sexp::make_number(count)); - lst.add_prop(":unread", Sexp::make_number(unread)); + qresults.add(Sexp::make_list(std::move(lst))); + } - qresults.add(Sexp::make_list(std::move(lst))); - } + Sexp::List addrs; + for (auto&& addr : store().metadata().personal_addresses) + addrs.add(Sexp::make_string(addr)); - Sexp::List addrs; - for (auto&& addr: store().metadata().personal_addresses) - addrs.add(Sexp::make_string(addr)); + Sexp::List lst; + lst.add_prop(":pong", Sexp::make_string("mu")); - Sexp::List lst; - lst.add_prop(":pong", Sexp::make_string("mu")); + Sexp::List proplst; + proplst.add_prop(":version", Sexp::make_string(VERSION)); + proplst.add_prop(":personal-addresses", Sexp::make_list(std::move(addrs))); + proplst.add_prop(":database-path", Sexp::make_string(store().metadata().database_path)); + proplst.add_prop(":root-maildir", Sexp::make_string(store().metadata().root_maildir)); + proplst.add_prop(":doccount", Sexp::make_number(storecount)); + proplst.add_prop(":queries", Sexp::make_list(std::move(qresults))); - Sexp::List proplst; - proplst.add_prop(":version", Sexp::make_string(VERSION)); - proplst.add_prop(":personal-addresses", Sexp::make_list(std::move(addrs))); - proplst.add_prop(":database-path", - Sexp::make_string(store().metadata().database_path)); - proplst.add_prop(":root-maildir", - Sexp::make_string(store().metadata().root_maildir)); - proplst.add_prop(":doccount", Sexp::make_number(storecount)); - proplst.add_prop(":queries", Sexp::make_list(std::move(qresults))); + lst.add_prop(":props", Sexp::make_list(std::move(proplst))); - lst.add_prop(":props", Sexp::make_list(std::move(proplst))); - - output_sexp(std::move(lst)); + output_sexp(std::move(lst)); } void -Server::Private::quit_handler (const Parameters& params) +Server::Private::quit_handler(const Parameters& params) { - keep_going_ = false; + keep_going_ = false; } - void -Server::Private::remove_handler (const Parameters& params) +Server::Private::remove_handler(const Parameters& params) { - const auto docid{get_int_or(params, ":docid")}; - const auto path{path_from_docid (store(), docid)}; + const auto docid{get_int_or(params, ":docid")}; + const auto path{path_from_docid(store(), docid)}; - if (::unlink (path.c_str()) != 0 && errno != ENOENT) - throw Error(Error::Code::File, "could not delete %s: %s", - path.c_str(), g_strerror (errno)); + if (::unlink(path.c_str()) != 0 && errno != ENOENT) + throw Error(Error::Code::File, + "could not delete %s: %s", + path.c_str(), + g_strerror(errno)); - if (!store().remove_message (path)) - g_warning("failed to remove message @ %s (%d) from store", - path.c_str(), docid); - // act as if it worked. + if (!store().remove_message(path)) + g_warning("failed to remove message @ %s (%d) from store", path.c_str(), docid); + // act as if it worked. - Sexp::List lst; - lst.add_prop(":remove", Sexp::make_number(docid)); + Sexp::List lst; + lst.add_prop(":remove", Sexp::make_number(docid)); - output_sexp(std::move(lst)); + output_sexp(std::move(lst)); } - void -Server::Private::sent_handler (const Parameters& params) +Server::Private::sent_handler(const Parameters& params) { - const auto path{get_string_or(params, ":path")}; - const auto docid{store().add_message(path)}; - if (docid == Store::InvalidId) - throw Error{Error::Code::Store, "failed to add path"}; + const auto path{get_string_or(params, ":path")}; + const auto docid{store().add_message(path)}; + if (docid == Store::InvalidId) + throw Error{Error::Code::Store, "failed to add path"}; - Sexp::List lst; - lst.add_prop (":sent", Sexp::make_symbol("t")); - lst.add_prop (":path", Sexp::make_string(path)); - lst.add_prop (":docid", Sexp::make_number(docid)); + Sexp::List lst; + lst.add_prop(":sent", Sexp::make_symbol("t")); + lst.add_prop(":path", Sexp::make_string(path)); + lst.add_prop(":docid", Sexp::make_number(docid)); - output_sexp (std::move(lst)); + output_sexp(std::move(lst)); } - bool -Server::Private::maybe_mark_as_read (MuMsg *msg, Store::Id docid) +Server::Private::maybe_mark_as_read(MuMsg* msg, Store::Id docid) { - if (!msg) - throw Error{Error::Code::Store, "missing message"}; + if (!msg) + throw Error{Error::Code::Store, "missing message"}; - const auto oldflags{mu_msg_get_flags (msg)}; - const auto newflags{get_flags (mu_msg_get_path(msg), "+S-u-N")}; - if (oldflags == newflags) - return false; // nothing to do. + const auto oldflags{mu_msg_get_flags(msg)}; + const auto newflags{get_flags(mu_msg_get_path(msg), "+S-u-N")}; + if (oldflags == newflags) + return false; // nothing to do. - GError* gerr{}; - if (!mu_msg_move_to_maildir (msg, - mu_msg_get_maildir (msg), - newflags, - TRUE, - FALSE,/*new_name,*/ - &gerr)) - throw Error{Error::Code::File, &gerr, "failed to move message"}; + GError* gerr{}; + if (!mu_msg_move_to_maildir(msg, + mu_msg_get_maildir(msg), + newflags, + TRUE, + FALSE, /*new_name,*/ + &gerr)) + throw Error{Error::Code::File, &gerr, "failed to move message"}; - /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir fields - * will be updated as wel */ - if (!store().update_message (msg, docid)) - throw Error{Error::Code::Store, "failed to store updated message"}; + /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir fields + * will be updated as wel */ + if (!store().update_message(msg, docid)) + throw Error{Error::Code::Store, "failed to store updated message"}; - /* send an update */ - Sexp::List update; - update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_NONE)); - output_sexp(Sexp::make_list(std::move(update))); + /* send an update */ + Sexp::List update; + update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_NONE)); + output_sexp(Sexp::make_list(std::move(update))); - g_debug ("marked message %d as read => %s", docid, mu_msg_get_path(msg)); + g_debug("marked message %d as read => %s", docid, mu_msg_get_path(msg)); - return true; + return true; } - bool -Server::Private::maybe_mark_msgid_as_read (const Mu::Query& query, const char* msgid) +Server::Private::maybe_mark_msgid_as_read(const Mu::Query& query, const char* msgid) { - if (!msgid) - return false; // nothing to do. + if (!msgid) + return false; // nothing to do. - const auto docids{docids_for_msgid(query, std::string{msgid})}; - for (auto&& docid: docids) { - MuMsg *msg = store().find_message(docid); - if (!msg) - continue; - try { - maybe_mark_as_read(msg, docid); - } catch (...) { - mu_msg_unref(msg); - throw; - } - } + const auto docids{docids_for_msgid(query, std::string{msgid})}; + for (auto&& docid : docids) { + MuMsg* msg = store().find_message(docid); + if (!msg) + continue; + try { + maybe_mark_as_read(msg, docid); + } catch (...) { + mu_msg_unref(msg); + throw; + } + } - return true; + return true; } void -Server::Private::view_handler (const Parameters& params) +Server::Private::view_handler(const Parameters& params) { - Store::Id docid{Store::InvalidId}; - const auto path{get_string_or(params, ":path")}; - const auto mark_as_read{get_bool_or(params, ":mark-as-read")}; + Store::Id docid{Store::InvalidId}; + const auto path{get_string_or(params, ":path")}; + const auto mark_as_read{get_bool_or(params, ":mark-as-read")}; - GError *gerr{}; - MuMsg *msg{}; + GError* gerr{}; + MuMsg* msg{}; - if (!path.empty()) { /* only use for old view (embedded msgs) */ - docid = Store::InvalidId; - msg = mu_msg_new_from_file (path.c_str(), NULL, &gerr); - } else { - docid = determine_docids(query(), params).at(0); - msg = store().find_message(docid); - } + if (!path.empty()) { /* only use for old view (embedded msgs) */ + docid = Store::InvalidId; + msg = mu_msg_new_from_file(path.c_str(), NULL, &gerr); + } else { + docid = determine_docids(query(), params).at(0); + msg = store().find_message(docid); + } - if (!msg) - throw Error{Error::Code::Store, &gerr, - "failed to find message for view"}; + if (!msg) + throw Error{Error::Code::Store, &gerr, "failed to find message for view"}; - if (mark_as_read) { - // maybe mark the main message as read. - maybe_mark_as_read(msg, docid); - /* maybe mark _all_ messsage with same message-id as read */ - maybe_mark_msgid_as_read(query(), mu_msg_get_msgid(msg)); - } + if (mark_as_read) { + // maybe mark the main message as read. + maybe_mark_as_read(msg, docid); + /* maybe mark _all_ messsage with same message-id as read */ + maybe_mark_msgid_as_read(query(), mu_msg_get_msgid(msg)); + } - Sexp::List seq; - seq.add_prop(":view", build_message_sexp( - msg, docid, {}, MU_MSG_OPTION_NONE)); - mu_msg_unref(msg); - output_sexp (std::move(seq)); + Sexp::List seq; + seq.add_prop(":view", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_NONE)); + mu_msg_unref(msg); + output_sexp(std::move(seq)); } -Server::Server(Store& store, Server::Output output): - priv_{std::make_unique(store, output)} -{} +Server::Server(Store& store, Server::Output output) + : priv_{std::make_unique(store, output)} +{ +} Server::~Server() = default; bool -Server::invoke (const std::string& expr) noexcept +Server::invoke(const std::string& expr) noexcept { - return priv_->invoke(expr); + return priv_->invoke(expr); } diff --git a/lib/mu-server.hh b/lib/mu-server.hh index 982b9ecc..d2784748 100644 --- a/lib/mu-server.hh +++ b/lib/mu-server.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_SERVER_HH__ #define MU_SERVER_HH__ @@ -34,35 +33,35 @@ namespace Mu { * */ class Server { -public: - using Output = std::function; + public: + using Output = std::function; - /** - * Construct a new server - * - * @param store a message store object - * @param output callable for the server responses. - */ - Server(Store& store, Output output); + /** + * Construct a new server + * + * @param store a message store object + * @param output callable for the server responses. + */ + Server(Store& store, Output output); - /** - * DTOR - */ - ~Server(); + /** + * DTOR + */ + ~Server(); - /** - * Invoke a call on the server. - * - * @param expr the s-expression to call - * - * @return true if we the server is still ready for more - * calls, false when it should quit. - */ - bool invoke(const std::string& expr) noexcept; + /** + * Invoke a call on the server. + * + * @param expr the s-expression to call + * + * @return true if we the server is still ready for more + * calls, false when it should quit. + */ + bool invoke(const std::string& expr) noexcept; -private: - struct Private; - std::unique_ptr priv_; + private: + struct Private; + std::unique_ptr priv_; }; } // namespace Mu diff --git a/lib/mu-store.cc b/lib/mu-store.cc index 7abd3fd3..e1b1a372 100644 --- a/lib/mu-store.cc +++ b/lib/mu-store.cc @@ -33,7 +33,6 @@ #include - #include "mu-store.hh" #include "utils/mu-str.h" #include "utils/mu-error.hh" @@ -43,8 +42,7 @@ using namespace Mu; -static_assert(std::is_same::value, - "wrong type for Store::Id"); +static_assert(std::is_same::value, "wrong type for Store::Id"); constexpr auto SchemaVersionKey = "schema-version"; constexpr auto RootMaildirKey = "maildir"; // XXX: make this 'root-maildir' @@ -62,1023 +60,984 @@ constexpr auto ExpectedSchemaVersion = MU_STORE_SCHEMA_VERSION; /* we cache these prefix strings, so we don't have to allocate them all * the time; this should save 10-20 string allocs per message */ G_GNUC_CONST static const std::string& -prefix (MuMsgFieldId mfid) +prefix(MuMsgFieldId mfid) { - static std::string fields[MU_MSG_FIELD_ID_NUM]; - static bool initialized = false; + static std::string fields[MU_MSG_FIELD_ID_NUM]; + static bool initialized = false; - if (G_UNLIKELY(!initialized)) { - for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) - fields[i] = std::string (1, mu_msg_field_xapian_prefix - ((MuMsgFieldId)i)); - initialized = true; - } + if (G_UNLIKELY(!initialized)) { + for (int i = 0; i != MU_MSG_FIELD_ID_NUM; ++i) + fields[i] = std::string(1, mu_msg_field_xapian_prefix((MuMsgFieldId)i)); + initialized = true; + } - return fields[mfid]; + return fields[mfid]; } static void -add_synonym_for_flag (MuFlags flag, Xapian::WritableDatabase *db) +add_synonym_for_flag(MuFlags flag, Xapian::WritableDatabase* db) { - static const std::string pfx(prefix(MU_MSG_FIELD_ID_FLAGS)); + static const std::string pfx(prefix(MU_MSG_FIELD_ID_FLAGS)); - db->clear_synonyms (pfx + mu_flag_name (flag)); - db->add_synonym (pfx + mu_flag_name (flag), pfx + - (std::string(1, (char)(tolower(mu_flag_char(flag)))))); + db->clear_synonyms(pfx + mu_flag_name(flag)); + db->add_synonym(pfx + mu_flag_name(flag), + pfx + (std::string(1, (char)(tolower(mu_flag_char(flag)))))); } - static void -add_synonym_for_prio (MuMsgPrio prio, Xapian::WritableDatabase *db) +add_synonym_for_prio(MuMsgPrio prio, Xapian::WritableDatabase* db) { - static const std::string pfx (prefix(MU_MSG_FIELD_ID_PRIO)); + static const std::string pfx(prefix(MU_MSG_FIELD_ID_PRIO)); - std::string s1 (pfx + mu_msg_prio_name (prio)); - std::string s2 (pfx + (std::string(1, mu_msg_prio_char (prio)))); + std::string s1(pfx + mu_msg_prio_name(prio)); + std::string s2(pfx + (std::string(1, mu_msg_prio_char(prio)))); - db->clear_synonyms (s1); - db->clear_synonyms (s2); + db->clear_synonyms(s1); + db->clear_synonyms(s2); - db->add_synonym (s1, s2); + db->add_synonym(s1, s2); } struct Store::Private { - #define LOCKED std::lock_guard l(lock_); - enum struct XapianOpts {ReadOnly, Open, CreateOverwrite, InMemory }; + enum struct XapianOpts { ReadOnly, Open, CreateOverwrite, InMemory }; - Private (const std::string& path, bool readonly): - read_only_{readonly}, - db_{make_xapian_db(path, read_only_ ? XapianOpts::ReadOnly : XapianOpts::Open)}, - mdata_{make_metadata(path)}, - contacts_{db().get_metadata(ContactsKey), mdata_.personal_addresses} { + Private(const std::string& path, bool readonly) + : read_only_{readonly}, db_{make_xapian_db(path, + read_only_ ? XapianOpts::ReadOnly + : XapianOpts::Open)}, + mdata_{make_metadata(path)}, contacts_{db().get_metadata(ContactsKey), + mdata_.personal_addresses} + { + } - if (!readonly) - writable_db().begin_transaction(); - } + Private(const std::string& path, + const std::string& root_maildir, + const StringVec& personal_addresses, + const Store::Config& conf) + : read_only_{false}, db_{make_xapian_db(path, XapianOpts::CreateOverwrite)}, + mdata_{init_metadata(conf, path, root_maildir, personal_addresses)}, + contacts_{"", mdata_.personal_addresses} + { + } - Private (const std::string& path, const std::string& root_maildir, - const StringVec& personal_addresses, const Store::Config& conf): - read_only_{false}, - db_{make_xapian_db(path, XapianOpts::CreateOverwrite)}, - mdata_{init_metadata(conf, path, root_maildir, personal_addresses)}, - contacts_{"", mdata_.personal_addresses} { + Private(const std::string& root_maildir, + const StringVec& personal_addresses, + const Store::Config& conf) + : read_only_{false}, db_{make_xapian_db("", XapianOpts::InMemory)}, + mdata_{init_metadata(conf, "", root_maildir, personal_addresses)}, + contacts_{"", mdata_.personal_addresses} + { + } - writable_db().begin_transaction(); - } + ~Private() + { + g_debug("closing store @ %s", mdata_.database_path.c_str()); + if (!read_only_) { + xapian_try([&] { + writable_db().set_metadata(ContactsKey, contacts_.serialize()); + }); + if (in_transaction_) + commit_transaction(); + } + } - Private (const std::string& root_maildir, - const StringVec& personal_addresses, const Store::Config& conf): - read_only_{false}, - db_{make_xapian_db("", XapianOpts::InMemory)}, - mdata_{init_metadata(conf, "", root_maildir, personal_addresses)}, - contacts_{"", mdata_.personal_addresses} { - } + std::unique_ptr make_xapian_db(const std::string db_path, XapianOpts opts) + try { + switch (opts) { + case XapianOpts::ReadOnly: return std::make_unique(db_path); + case XapianOpts::Open: + return std::make_unique(db_path, Xapian::DB_OPEN); + case XapianOpts::CreateOverwrite: + return std::make_unique( + db_path, + Xapian::DB_CREATE_OR_OVERWRITE); + case XapianOpts::InMemory: + return std::make_unique( + std::string{}, + Xapian::DB_BACKEND_INMEMORY); + default: throw std::logic_error("invalid xapian options"); + } - ~Private() try { - g_debug("closing store @ %s", mdata_.database_path.c_str()); - if (!read_only_) { - writable_db().set_metadata (ContactsKey, contacts_.serialize()); - commit(); - } - } MU_XAPIAN_CATCH_BLOCK; + } catch (const Xapian::DatabaseError& xde) { + throw Mu::Error(Error::Code::Store, + "failed to open store @ %s: %s", + db_path.c_str(), + xde.get_msg().c_str()); + } catch (...) { + throw Mu::Error(Error::Code::Internal, + "something went wrong when opening store @ %s", + db_path.c_str()); + } - std::unique_ptr make_xapian_db (const std::string db_path, XapianOpts opts) try { + const Xapian::Database& db() const { return *db_.get(); } - switch (opts) { - case XapianOpts::ReadOnly: - return std::make_unique(db_path); - case XapianOpts::Open: - return std::make_unique(db_path, Xapian::DB_OPEN); - case XapianOpts::CreateOverwrite: - return std::make_unique(db_path, Xapian::DB_CREATE_OR_OVERWRITE); - case XapianOpts::InMemory: - return std::make_unique(std::string{}, Xapian::DB_BACKEND_INMEMORY); - default: - throw std::logic_error ("invalid xapian options"); - } + Xapian::WritableDatabase& writable_db() + { + if (read_only_) + throw Mu::Error(Error::Code::AccessDenied, "database is read-only"); + return dynamic_cast(*db_.get()); + } - } catch (const Xapian::DatabaseError& xde) { - throw Mu::Error(Error::Code::Store, "failed to open store @ %s: %s", - db_path.c_str(), xde.get_msg().c_str()); - } catch (...) { - throw Mu::Error(Error::Code::Internal, - "something went wrong when opening store @ %s", - db_path.c_str()); - } + void begin_transaction() noexcept + { + if (mdata_.in_memory) + return; // not supported in the in-memory backend. - const Xapian::Database& db() const { return *db_.get(); } + g_return_if_fail(!in_transaction_); + g_debug("starting transaction"); + xapian_try([this] { + writable_db().begin_transaction(); + in_transaction_ = true; + }); + } - Xapian::WritableDatabase& writable_db() { - if (read_only_) - throw Mu::Error(Error::Code::AccessDenied, "database is read-only"); - return dynamic_cast(*db_.get()); - } + void commit_transaction() noexcept + { + if (mdata_.in_memory) + return; // not supported in the in-memory backend. - void dirty () try { - if (++dirtiness_ > mdata_.batch_size) - commit(); - } MU_XAPIAN_CATCH_BLOCK; + g_return_if_fail(in_transaction_); + g_debug("committing modification(s)"); + xapian_try([this] { + if (in_transaction_) + writable_db().commit_transaction(); + in_transaction_ = false; + }); + } - void commit () try { - g_debug("committing %zu modification(s)", dirtiness_); - dirtiness_ = 0; - if (mdata_.in_memory) - return; // not supported in the in-memory backend. - writable_db().commit_transaction(); - writable_db().begin_transaction(); - } MU_XAPIAN_CATCH_BLOCK; + void add_synonyms() + { + mu_flags_foreach((MuFlagsForeachFunc)add_synonym_for_flag, &writable_db()); + mu_msg_prio_foreach((MuMsgPrioForeachFunc)add_synonym_for_prio, &writable_db()); + } - void add_synonyms () { - mu_flags_foreach ((MuFlagsForeachFunc)add_synonym_for_flag, - &writable_db()); - mu_msg_prio_foreach ((MuMsgPrioForeachFunc)add_synonym_for_prio, - &writable_db()); - } + time_t metadata_time_t(const std::string& key) const + { + const auto ts = db().get_metadata(key); + return (time_t)atoll(db().get_metadata(key).c_str()); + } - time_t metadata_time_t (const std::string& key) const { - const auto ts = db().get_metadata(key); - return (time_t)atoll(db().get_metadata(key).c_str()); - } + Store::Metadata make_metadata(const std::string& db_path) + { + Store::Metadata mdata; - Store::Metadata make_metadata(const std::string& db_path) { - Store::Metadata mdata; + mdata.database_path = db_path; + mdata.schema_version = db().get_metadata(SchemaVersionKey); + mdata.created = ::atoll(db().get_metadata(CreatedKey).c_str()); + mdata.read_only = read_only_; - mdata.database_path = db_path; - mdata.schema_version = db().get_metadata(SchemaVersionKey); - mdata.created = ::atoll(db().get_metadata(CreatedKey).c_str()); - mdata.read_only = read_only_; + mdata.batch_size = ::atoll(db().get_metadata(BatchSizeKey).c_str()); + mdata.max_message_size = ::atoll(db().get_metadata(MaxMessageSizeKey).c_str()); + mdata.in_memory = db_path.empty(); - mdata.batch_size = ::atoll(db().get_metadata(BatchSizeKey).c_str()); - mdata.max_message_size = ::atoll(db().get_metadata(MaxMessageSizeKey).c_str()); - mdata.in_memory = db_path.empty(); + mdata.root_maildir = db().get_metadata(RootMaildirKey); + mdata.personal_addresses = Mu::split(db().get_metadata(PersonalAddressesKey), ","); - mdata.root_maildir = db().get_metadata(RootMaildirKey); - mdata.personal_addresses = Mu::split(db().get_metadata(PersonalAddressesKey),","); + return mdata; + } - return mdata; - } + Store::Metadata init_metadata(const Store::Config& conf, + const std::string& path, + const std::string& root_maildir, + const StringVec& personal_addresses) + { + writable_db().set_metadata(SchemaVersionKey, ExpectedSchemaVersion); + writable_db().set_metadata(CreatedKey, Mu::format("%" PRId64, (int64_t)::time({}))); - Store::Metadata init_metadata(const Store::Config& conf, - const std::string& path, const std::string& root_maildir, - const StringVec& personal_addresses) { + const size_t batch_size = conf.batch_size ? conf.batch_size : DefaultBatchSize; + writable_db().set_metadata(BatchSizeKey, Mu::format("%zu", batch_size)); - writable_db().set_metadata(SchemaVersionKey, ExpectedSchemaVersion); - writable_db().set_metadata(CreatedKey, Mu::format("%" PRId64, (int64_t)::time({}))); + const size_t max_msg_size = conf.max_message_size ? conf.max_message_size + : DefaultMaxMessageSize; + writable_db().set_metadata(MaxMessageSizeKey, Mu::format("%zu", max_msg_size)); - const size_t batch_size = conf.batch_size ? conf.batch_size : DefaultBatchSize; - writable_db().set_metadata(BatchSizeKey, Mu::format("%zu", batch_size)); + writable_db().set_metadata(RootMaildirKey, root_maildir); - const size_t max_msg_size = conf.max_message_size ? - conf.max_message_size : DefaultMaxMessageSize; - writable_db().set_metadata(MaxMessageSizeKey, Mu::format("%zu", max_msg_size)); + std::string addrs; + for (const auto& addr : personal_addresses) { // _very_ minimal check. + if (addr.find(",") != std::string::npos) + throw Mu::Error(Error::Code::InvalidArgument, + "e-mail address '%s' contains comma", + addr.c_str()); + addrs += (addrs.empty() ? "" : ",") + addr; + } + writable_db().set_metadata(PersonalAddressesKey, addrs); - writable_db().set_metadata(RootMaildirKey, root_maildir); + return make_metadata(path); + } - std::string addrs; - for (const auto& addr : personal_addresses) { // _very_ minimal check. - if (addr.find(",") != std::string::npos) - throw Mu::Error(Error::Code::InvalidArgument, - "e-mail address '%s' contains comma", addr.c_str()); - addrs += (addrs.empty() ? "": ",") + addr; - } - writable_db().set_metadata (PersonalAddressesKey, addrs); + Xapian::docid add_or_update_msg(Xapian::docid docid, MuMsg* msg); + Xapian::Document new_doc_from_message(MuMsg* msg); - return make_metadata(path); - } + const bool read_only_{}; + std::unique_ptr db_; - Xapian::docid add_or_update_msg (Xapian::docid docid, MuMsg *msg, GError **err); - Xapian::Document new_doc_from_message (MuMsg *msg); + const Store::Metadata mdata_; + Contacts contacts_; + std::unique_ptr indexer_; - const bool read_only_{}; - std::unique_ptr db_; - - const Store::Metadata mdata_; - Contacts contacts_; - std::unique_ptr indexer_; - - std::atomic in_transaction_{}; - std::mutex lock_; - size_t dirtiness_{}; - - mutable std::atomic ref_count_{1}; + std::atomic in_transaction_{}; + std::mutex lock_; }; - static void -hash_str (char *buf, size_t buf_size, const char *data) +hash_str(char* buf, size_t buf_size, const char* data) { - g_snprintf(buf, buf_size, "016%" PRIx64, mu_util_get_hash(data)); + g_snprintf(buf, buf_size, "016%" PRIx64, mu_util_get_hash(data)); } - static std::string -get_uid_term (const char* path) +get_uid_term(const char* path) { - char uid_term[1 + 16 + 1] = {'\0'}; - uid_term[0] = mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); - hash_str(uid_term + 1, sizeof(uid_term)-1, path); + char uid_term[1 + 16 + 1] = {'\0'}; + uid_term[0] = mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); + hash_str(uid_term + 1, sizeof(uid_term) - 1, path); - return std::string{uid_term, sizeof(uid_term)}; + return std::string{uid_term, sizeof(uid_term)}; } -#undef LOCKED -#define LOCKED std::lock_guard l__(priv_->lock_) +#undef LOCKED +#define LOCKED std::lock_guard l__(priv_->lock_) -Store::Store (const std::string& path, bool readonly): - priv_{std::make_unique(path, readonly)} +Store::Store(const std::string& path, bool readonly) + : priv_{std::make_unique(path, readonly)} { - if (metadata().schema_version != ExpectedSchemaVersion) - throw Mu::Error(Error::Code::SchemaMismatch, - "expected schema-version %s, but got %s; " - "please use 'mu init'", - ExpectedSchemaVersion, - metadata().schema_version.c_str()); + if (metadata().schema_version != ExpectedSchemaVersion) + throw Mu::Error(Error::Code::SchemaMismatch, + "expected schema-version %s, but got %s; " + "please use 'mu init'", + ExpectedSchemaVersion, + metadata().schema_version.c_str()); } -Store::Store (const std::string& path, const std::string& maildir, - const StringVec& personal_addresses, const Store::Config& conf): - priv_{std::make_unique(path, maildir, personal_addresses, conf)} -{} - - -Store::Store (const std::string& maildir, - const StringVec& personal_addresses, const Config& conf): - priv_{std::make_unique(maildir, personal_addresses, conf)} -{} +Store::Store(const std::string& path, + const std::string& maildir, + const StringVec& personal_addresses, + const Store::Config& conf) + : priv_{std::make_unique(path, maildir, personal_addresses, conf)} +{ +} +Store::Store(const std::string& maildir, const StringVec& personal_addresses, const Config& conf) + : priv_{std::make_unique(maildir, personal_addresses, conf)} +{ +} Store::~Store() = default; const Store::Metadata& Store::metadata() const { - return priv_->mdata_; + return priv_->mdata_; } const Contacts& Store::contacts() const { - return priv_->contacts_; + return priv_->contacts_; } - const Xapian::Database& Store::database() const { - return priv_->db(); + return priv_->db(); } Xapian::WritableDatabase& Store::writable_database() { - return priv_->writable_db(); + return priv_->writable_db(); } Indexer& Store::indexer() { - LOCKED; + LOCKED; - if (metadata().read_only) - throw Error{Error::Code::Store, "no indexer for read-only store"}; - else if (!priv_->indexer_) - priv_->indexer_ = std::make_unique(*this); + if (metadata().read_only) + throw Error{Error::Code::Store, "no indexer for read-only store"}; + else if (!priv_->indexer_) + priv_->indexer_ = std::make_unique(*this); - return *priv_->indexer_.get(); + return *priv_->indexer_.get(); } std::size_t Store::size() const { - LOCKED; - return priv_->db().get_doccount(); + LOCKED; + return priv_->db().get_doccount(); } bool Store::empty() const { - return size() == 0; + return size() == 0; } static std::string -maildir_from_path (const std::string& root, const std::string& path) +maildir_from_path(const std::string& root, const std::string& path) { - if (G_UNLIKELY(root.empty()) || root.length() >= path.length() || - path.find(root) != 0) - throw Mu::Error{Error::Code::InvalidArgument, - "root '%s' is not a proper suffix of path '%s'", - root.c_str(), path.c_str()}; + if (G_UNLIKELY(root.empty()) || root.length() >= path.length() || path.find(root) != 0) + throw Mu::Error{Error::Code::InvalidArgument, + "root '%s' is not a proper suffix of path '%s'", + root.c_str(), + path.c_str()}; - auto mdir{path.substr(root.length())}; - auto slash{mdir.rfind('/')}; + auto mdir{path.substr(root.length())}; + auto slash{mdir.rfind('/')}; - if (G_UNLIKELY(slash == std::string::npos) || slash < 4) - throw Mu::Error{Error::Code::InvalidArgument, - "invalid path: %s", path.c_str()}; - mdir.erase(slash); - auto subdir=mdir.data()+slash-4; - if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && - strncmp(subdir, "/new", 4))) - throw Mu::Error{Error::Code::InvalidArgument, - "cannot find '/new' or '/cur' - invalid path: %s", path.c_str()}; - if (mdir.length() == 4) - return "/"; + if (G_UNLIKELY(slash == std::string::npos) || slash < 4) + throw Mu::Error{Error::Code::InvalidArgument, "invalid path: %s", path.c_str()}; + mdir.erase(slash); + auto subdir = mdir.data() + slash - 4; + if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && strncmp(subdir, "/new", 4))) + throw Mu::Error{Error::Code::InvalidArgument, + "cannot find '/new' or '/cur' - invalid path: %s", + path.c_str()}; + if (mdir.length() == 4) + return "/"; - mdir.erase(mdir.length()-4); - return mdir; + mdir.erase(mdir.length() - 4); + return mdir; } unsigned -Store::add_message (const std::string& path) +Store::add_message(const std::string& path) { - LOCKED; + LOCKED; - GError *gerr{}; - const auto maildir{maildir_from_path(metadata().root_maildir, path)}; - auto msg{mu_msg_new_from_file (path.c_str(), maildir.c_str(), &gerr)}; - if (G_UNLIKELY(!msg)) - throw Error{Error::Code::Message, "failed to create message: %s", - gerr ? gerr->message : "something went wrong"}; + GError* gerr{}; + const auto maildir{maildir_from_path(metadata().root_maildir, path)}; + auto msg{mu_msg_new_from_file(path.c_str(), maildir.c_str(), &gerr)}; + if (G_UNLIKELY(!msg)) + throw Error{Error::Code::Message, + "failed to create message: %s", + gerr ? gerr->message : "something went wrong"}; - const auto docid{priv_->add_or_update_msg (0, msg, &gerr)}; - mu_msg_unref (msg); - if (G_UNLIKELY(docid == InvalidId)) - throw Error{Error::Code::Message, "failed to add message: %s", - gerr ? gerr->message : "something went wrong"}; + const auto docid{priv_->add_or_update_msg(0, msg)}; + mu_msg_unref(msg); - g_debug ("added message @ %s; docid = %u", path.c_str(), docid); - priv_->dirty(); + if (G_UNLIKELY(docid == InvalidId)) + throw Error{Error::Code::Message, "failed to add message"}; - return docid; + g_debug("added message @ %s; docid = %u", path.c_str(), docid); + + return docid; } bool -Store::update_message (MuMsg *msg, unsigned docid) +Store::update_message(MuMsg* msg, unsigned docid) { - GError *gerr{}; - const auto docid2{priv_->add_or_update_msg (docid, msg, &gerr)}; + const auto docid2{priv_->add_or_update_msg(docid, msg)}; - if (G_UNLIKELY(docid != docid2)) - throw Error{Error::Code::Internal, "failed to update message", - gerr ? gerr->message : "something went wrong"}; + if (G_UNLIKELY(docid != docid2)) + throw Error{Error::Code::Internal, "failed to update message"}; - g_debug ("updated message @ %s; docid = %u", - mu_msg_get_path(msg), docid); - priv_->dirty(); + g_debug("updated message @ %s; docid = %u", mu_msg_get_path(msg), docid); - return true; + return true; } - bool -Store::remove_message (const std::string& path) +Store::remove_message(const std::string& path) { - LOCKED; + return xapian_try( + [&] { + LOCKED; + const std::string term{(get_uid_term(path.c_str()))}; + priv_->writable_db().delete_document(term); - try { - const std::string term{(get_uid_term(path.c_str()))}; - priv_->writable_db().delete_document(term); + g_debug("deleted message @ %s from store", path.c_str()); - } MU_XAPIAN_CATCH_BLOCK_RETURN (false); - - g_debug ("deleted message @ %s from store", path.c_str()); - priv_->dirty(); - - return true; + return true; + }, + false); } - void -Store::remove_messages (const std::vector& ids) +Store::remove_messages(const std::vector& ids) { - LOCKED; + begin_transaction(); - try { - for (auto&& id: ids) { - priv_->writable_db().delete_document(id); - priv_->dirty(); - } + xapian_try([&] { + LOCKED; + for (auto&& id : ids) { + priv_->writable_db().delete_document(id); + } + }); - } MU_XAPIAN_CATCH_BLOCK; + commit_transaction(); } time_t -Store::dirstamp (const std::string& path) const +Store::dirstamp(const std::string& path) const { - LOCKED; + LOCKED; - const auto ts = priv_->db().get_metadata(path); - if (ts.empty()) - return 0; - else - return (time_t)strtoll(ts.c_str(), NULL, 16); + const auto ts = priv_->db().get_metadata(path); + if (ts.empty()) + return 0; + else + return (time_t)strtoll(ts.c_str(), NULL, 16); } void -Store::set_dirstamp (const std::string& path, time_t tstamp) +Store::set_dirstamp(const std::string& path, time_t tstamp) { - LOCKED; + LOCKED; - std::array data{}; - const std::size_t len = g_snprintf (data.data(), data.size(), "%zx", (size_t)tstamp); + std::array data{}; + const std::size_t len = g_snprintf(data.data(), data.size(), "%zx", (size_t)tstamp); - priv_->writable_db().set_metadata(path, std::string{data.data(), len}); - priv_->dirty(); + priv_->writable_db().set_metadata(path, std::string{data.data(), len}); } - MuMsg* -Store::find_message (unsigned docid) const +Store::find_message(unsigned docid) const { - LOCKED; - - try { - Xapian::Document *doc{new Xapian::Document{priv_->db().get_document (docid)}}; - GError *gerr{}; - auto msg{mu_msg_new_from_doc (reinterpret_cast(doc), &gerr)}; - if (!msg) { - g_warning ("could not create message: %s", gerr ? gerr->message : - "something went wrong"); - g_clear_error(&gerr); - } - - return msg; - - } MU_XAPIAN_CATCH_BLOCK_RETURN (nullptr); + return xapian_try( + [&] { + LOCKED; + Xapian::Document* doc{new Xapian::Document{priv_->db().get_document(docid)}}; + GError* gerr{}; + auto msg{mu_msg_new_from_doc(reinterpret_cast(doc), &gerr)}; + if (!msg) { + g_warning("could not create message: %s", + gerr ? gerr->message : "something went wrong"); + g_clear_error(&gerr); + } + return msg; + }, + (MuMsg*)nullptr); } - bool -Store::contains_message (const std::string& path) const +Store::contains_message(const std::string& path) const { - LOCKED; - - try { - const std::string term (get_uid_term(path.c_str())); - return priv_->db().term_exists (term); - - } MU_XAPIAN_CATCH_BLOCK_RETURN(false); + return xapian_try( + [&] { + LOCKED; + const std::string term(get_uid_term(path.c_str())); + return priv_->db().term_exists(term); + }, + false); } - std::size_t -Store::for_each_message_path (Store::ForEachMessageFunc func) const +Store::for_each_message_path(Store::ForEachMessageFunc msg_func) const { - LOCKED; + size_t n{}; - size_t n{}; + xapian_try([&] { + LOCKED; + Xapian::Enquire enq{priv_->db()}; + enq.set_query(Xapian::Query::MatchAll); + enq.set_cutoff(0, 0); - try { - Xapian::Enquire enq{priv_->db()}; + Xapian::MSet matches(enq.get_mset(0, priv_->db().get_doccount())); + for (auto&& it = matches.begin(); it != matches.end(); ++it, ++n) + if (!msg_func(*it, it.get_document().get_value(MU_MSG_FIELD_ID_PATH))) + break; + }); - enq.set_query (Xapian::Query::MatchAll); - enq.set_cutoff (0,0); - - Xapian::MSet matches(enq.get_mset (0, priv_->db().get_doccount())); - - for (auto&& it = matches.begin(); it != matches.end(); ++it, ++n) - if (!func (*it, it.get_document().get_value(MU_MSG_FIELD_ID_PATH))) - break; - - } MU_XAPIAN_CATCH_BLOCK; - - return n; + return n; } static MuMsgFieldId -field_id (const std::string& field) +field_id(const std::string& field) { + if (field.empty()) + return MU_MSG_FIELD_ID_NONE; - if (field.empty()) - return MU_MSG_FIELD_ID_NONE; - - MuMsgFieldId id = mu_msg_field_id_from_name (field.c_str(), FALSE); - if (id != MU_MSG_FIELD_ID_NONE) - return id; - else if (field.length() == 1) - return mu_msg_field_id_from_shortcut (field[0], FALSE); - else - return MU_MSG_FIELD_ID_NONE; + MuMsgFieldId id = mu_msg_field_id_from_name(field.c_str(), FALSE); + if (id != MU_MSG_FIELD_ID_NONE) + return id; + else if (field.length() == 1) + return mu_msg_field_id_from_shortcut(field[0], FALSE); + else + return MU_MSG_FIELD_ID_NONE; } - - std::size_t -Store::for_each_term (const std::string& field, Store::ForEachTermFunc func) const +Store::for_each_term(const std::string& field, Store::ForEachTermFunc func) const { - LOCKED; + size_t n{}; - size_t n{}; + xapian_try([&] { + LOCKED; + const auto id = field_id(field.c_str()); + if (id == MU_MSG_FIELD_ID_NONE) + return; - try { - const auto id = field_id (field.c_str()); - if (id == MU_MSG_FIELD_ID_NONE) - return {}; + char pfx[] = {mu_msg_field_xapian_prefix(id), '\0'}; + std::vector terms; + for (auto it = priv_->db().allterms_begin(pfx); it != priv_->db().allterms_end(pfx); + ++it) { + if (!func(*it)) + break; + } + }); - char pfx[] = { mu_msg_field_xapian_prefix(id), '\0' }; - - std::vector terms; - for (auto it = priv_->db().allterms_begin(pfx); - it != priv_->db().allterms_end(pfx); ++it) { - if (!func(*it)) - break; - } - - } MU_XAPIAN_CATCH_BLOCK; - - return n; + return n; } void -Store::commit () try +Store::begin_transaction() { - LOCKED; - priv_->commit(); + xapian_try([&] { + LOCKED; + if (!priv_->in_transaction_) + priv_->begin_transaction(); + }); +} -} MU_XAPIAN_CATCH_BLOCK; - -static void -add_terms_values_date (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +void +Store::commit_transaction() { - const auto dstr = Mu::date_to_time_t_string ( - (time_t)mu_msg_get_field_numeric (msg, mfid)); - - doc.add_value ((Xapian::valueno)mfid, dstr); + xapian_try([&] { + LOCKED; + if (priv_->in_transaction_) + priv_->commit_transaction(); + }); } static void -add_terms_values_size (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +add_terms_values_date(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - const auto szstr = - Mu::size_to_string (mu_msg_get_field_numeric (msg, mfid)); - doc.add_value ((Xapian::valueno)mfid, szstr); + const auto dstr = Mu::date_to_time_t_string((time_t)mu_msg_get_field_numeric(msg, mfid)); + + doc.add_value((Xapian::valueno)mfid, dstr); +} + +static void +add_terms_values_size(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) +{ + const auto szstr = Mu::size_to_string(mu_msg_get_field_numeric(msg, mfid)); + doc.add_value((Xapian::valueno)mfid, szstr); } G_GNUC_CONST static const std::string& -flag_val (char flagchar) +flag_val(char flagchar) { - static const std::string - pfx (prefix(MU_MSG_FIELD_ID_FLAGS)), - draftstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_DRAFT))), - flaggedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_FLAGGED))), - passedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_PASSED))), - repliedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_REPLIED))), - seenstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_SEEN))), - trashedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_TRASHED))), - newstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_NEW))), - signedstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_SIGNED))), - cryptstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_ENCRYPTED))), - attachstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_HAS_ATTACH))), - unreadstr (pfx + (char)tolower(mu_flag_char(MU_FLAG_UNREAD))), - liststr (pfx + (char)tolower(mu_flag_char(MU_FLAG_LIST))); + static const std::string pfx(prefix(MU_MSG_FIELD_ID_FLAGS)), + draftstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_DRAFT))), + flaggedstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_FLAGGED))), + passedstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_PASSED))), + repliedstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_REPLIED))), + seenstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_SEEN))), + trashedstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_TRASHED))), + newstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_NEW))), + signedstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_SIGNED))), + cryptstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_ENCRYPTED))), + attachstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_HAS_ATTACH))), + unreadstr(pfx + (char)tolower(mu_flag_char(MU_FLAG_UNREAD))), + liststr(pfx + (char)tolower(mu_flag_char(MU_FLAG_LIST))); - switch (flagchar) { + switch (flagchar) { + case 'D': return draftstr; + case 'F': return flaggedstr; + case 'P': return passedstr; + case 'R': return repliedstr; + case 'S': return seenstr; + case 'T': return trashedstr; - case 'D': return draftstr; - case 'F': return flaggedstr; - case 'P': return passedstr; - case 'R': return repliedstr; - case 'S': return seenstr; - case 'T': return trashedstr; + case 'N': return newstr; - case 'N': return newstr; + case 'z': return signedstr; + case 'x': return cryptstr; + case 'a': return attachstr; + case 'l': return liststr; - case 'z': return signedstr; - case 'x': return cryptstr; - case 'a': return attachstr; - case 'l': return liststr; + case 'u': return unreadstr; - case 'u': return unreadstr; - - default: - g_return_val_if_reached (flaggedstr); - return flaggedstr; - } + default: g_return_val_if_reached(flaggedstr); return flaggedstr; + } } /* pre-calculate; optimization */ G_GNUC_CONST static const std::string& -prio_val (MuMsgPrio prio) +prio_val(MuMsgPrio prio) { - static const std::string pfx (prefix(MU_MSG_FIELD_ID_PRIO)); + static const std::string pfx(prefix(MU_MSG_FIELD_ID_PRIO)); - static const std::string - low (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_LOW))), - norm (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_NORMAL))), - high (pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_HIGH))); + static const std::string low(pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_LOW))), + norm(pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_NORMAL))), + high(pfx + std::string(1, mu_msg_prio_char(MU_MSG_PRIO_HIGH))); - switch (prio) { - case MU_MSG_PRIO_LOW: return low; - case MU_MSG_PRIO_NORMAL: return norm; - case MU_MSG_PRIO_HIGH: return high; - default: - g_return_val_if_reached (norm); - return norm; - } + switch (prio) { + case MU_MSG_PRIO_LOW: return low; + case MU_MSG_PRIO_NORMAL: return norm; + case MU_MSG_PRIO_HIGH: return high; + default: g_return_val_if_reached(norm); return norm; + } } - static void // add term, truncate if needed. -add_term (Xapian::Document& doc, const std::string& term) +add_term(Xapian::Document& doc, const std::string& term) { - if (term.length() < Store::MaxTermLength) - doc.add_term(term); - else - doc.add_term(term.substr(0, Store::MaxTermLength)); + if (term.length() < Store::MaxTermLength) + doc.add_term(term); + else + doc.add_term(term.substr(0, Store::MaxTermLength)); } - - static void -add_terms_values_number (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +add_terms_values_number(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - gint64 num = mu_msg_get_field_numeric (msg, mfid); + gint64 num = mu_msg_get_field_numeric(msg, mfid); - const std::string numstr (Xapian::sortable_serialise((double)num)); - doc.add_value ((Xapian::valueno)mfid, numstr); + const std::string numstr(Xapian::sortable_serialise((double)num)); + doc.add_value((Xapian::valueno)mfid, numstr); - if (mfid == MU_MSG_FIELD_ID_FLAGS) { - const char *cur = mu_flags_to_str_s - ((MuFlags)num,(MuFlagType)MU_FLAG_TYPE_ANY); - g_return_if_fail (cur); - while (*cur) { - add_term (doc, flag_val(*cur)); - ++cur; - } + if (mfid == MU_MSG_FIELD_ID_FLAGS) { + const char* cur = mu_flags_to_str_s((MuFlags)num, (MuFlagType)MU_FLAG_TYPE_ANY); + g_return_if_fail(cur); + while (*cur) { + add_term(doc, flag_val(*cur)); + ++cur; + } - } else if (mfid == MU_MSG_FIELD_ID_PRIO) - add_term (doc, prio_val((MuMsgPrio)num)); + } else if (mfid == MU_MSG_FIELD_ID_PRIO) + add_term(doc, prio_val((MuMsgPrio)num)); } - /* for string and string-list */ static void -add_terms_values_str (Xapian::Document& doc, const char *val, MuMsgFieldId mfid) +add_terms_values_str(Xapian::Document& doc, const char* val, MuMsgFieldId mfid) { - const auto flat = Mu::utf8_flatten (val); + const auto flat = Mu::utf8_flatten(val); - if (mu_msg_field_xapian_index (mfid)) { - Xapian::TermGenerator termgen; - termgen.set_document (doc); - termgen.index_text (flat, 1, prefix(mfid)); - } - - if (mu_msg_field_xapian_term(mfid)) - add_term(doc, prefix(mfid) + flat); + if (mu_msg_field_xapian_index(mfid)) { + Xapian::TermGenerator termgen; + termgen.set_document(doc); + termgen.index_text(flat, 1, prefix(mfid)); + } + if (mu_msg_field_xapian_term(mfid)) + add_term(doc, prefix(mfid) + flat); } static void -add_terms_values_string (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid) +add_terms_values_string(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - const char *orig; + const char* orig; - if (!(orig = mu_msg_get_field_string (msg, mfid))) - return; /* nothing to do */ + if (!(orig = mu_msg_get_field_string(msg, mfid))) + return; /* nothing to do */ - /* the value is what we display in search results; the - * unchanged original */ - if (mu_msg_field_xapian_value(mfid)) - doc.add_value ((Xapian::valueno)mfid, orig); + /* the value is what we display in search results; the + * unchanged original */ + if (mu_msg_field_xapian_value(mfid)) + doc.add_value((Xapian::valueno)mfid, orig); - add_terms_values_str (doc, orig, mfid); + add_terms_values_str(doc, orig, mfid); } static void -add_terms_values_string_list (Xapian::Document& doc, MuMsg *msg, - MuMsgFieldId mfid) +add_terms_values_string_list(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - const GSList *lst; + const GSList* lst; - lst = mu_msg_get_field_string_list (msg, mfid); - if (!lst) - return; + lst = mu_msg_get_field_string_list(msg, mfid); + if (!lst) + return; - if (mu_msg_field_xapian_value (mfid)) { - gchar *str; - str = mu_str_from_list (lst, ','); - if (str) - doc.add_value ((Xapian::valueno)mfid, str); - g_free (str); - } + if (mu_msg_field_xapian_value(mfid)) { + gchar* str; + str = mu_str_from_list(lst, ','); + if (str) + doc.add_value((Xapian::valueno)mfid, str); + g_free(str); + } - if (mu_msg_field_xapian_term (mfid)) { - for (; lst; lst = g_slist_next ((GSList*)lst)) - add_terms_values_str (doc, (const gchar*)lst->data, - mfid); - } + if (mu_msg_field_xapian_term(mfid)) { + for (; lst; lst = g_slist_next((GSList*)lst)) + add_terms_values_str(doc, (const gchar*)lst->data, mfid); + } } - struct PartData { - PartData (Xapian::Document& doc, MuMsgFieldId mfid): - _doc (doc), _mfid(mfid) {} - Xapian::Document _doc; - MuMsgFieldId _mfid; + PartData(Xapian::Document& doc, MuMsgFieldId mfid) : _doc(doc), _mfid(mfid) {} + Xapian::Document _doc; + MuMsgFieldId _mfid; }; /* index non-body text parts */ static void -maybe_index_text_part (MuMsg *msg, MuMsgPart *part, PartData *pdata) +maybe_index_text_part(MuMsg* msg, MuMsgPart* part, PartData* pdata) { - char *txt; - Xapian::TermGenerator termgen; + char* txt; + Xapian::TermGenerator termgen; - /* only deal with attachments/messages; inlines are indexed as - * body parts */ - if (!(part->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && - !(part->part_type & MU_MSG_PART_TYPE_MESSAGE)) - return; + /* only deal with attachments/messages; inlines are indexed as + * body parts */ + if (!(part->part_type & MU_MSG_PART_TYPE_ATTACHMENT) && + !(part->part_type & MU_MSG_PART_TYPE_MESSAGE)) + return; - txt = mu_msg_part_get_text (msg, part, MU_MSG_OPTION_NONE); - if (!txt) - return; + txt = mu_msg_part_get_text(msg, part, MU_MSG_OPTION_NONE); + if (!txt) + return; - termgen.set_document(pdata->_doc); - const auto str = Mu::utf8_flatten (txt); - g_free (txt); + termgen.set_document(pdata->_doc); + const auto str = Mu::utf8_flatten(txt); + g_free(txt); - termgen.index_text (str, 1, prefix(MU_MSG_FIELD_ID_EMBEDDED_TEXT)); + termgen.index_text(str, 1, prefix(MU_MSG_FIELD_ID_EMBEDDED_TEXT)); } - static void -each_part (MuMsg *msg, MuMsgPart *part, PartData *pdata) +each_part(MuMsg* msg, MuMsgPart* part, PartData* pdata) { - char *fname; - static const std::string - file (prefix(MU_MSG_FIELD_ID_FILE)), - mime (prefix(MU_MSG_FIELD_ID_MIME)); + char* fname; + static const std::string file(prefix(MU_MSG_FIELD_ID_FILE)), + mime(prefix(MU_MSG_FIELD_ID_MIME)); - /* save the mime type of any part */ - if (part->type) { - char ctype[Store::MaxTermLength + 1]; - g_snprintf(ctype, sizeof(ctype), "%s/%s", part->type, part->subtype); - add_term(pdata->_doc, mime + ctype); - } + /* save the mime type of any part */ + if (part->type) { + char ctype[Store::MaxTermLength + 1]; + g_snprintf(ctype, sizeof(ctype), "%s/%s", part->type, part->subtype); + add_term(pdata->_doc, mime + ctype); + } - if ((fname = mu_msg_part_get_filename (part, FALSE))) { - const auto flat = Mu::utf8_flatten (fname); - g_free (fname); - add_term(pdata->_doc, file + flat); - } + if ((fname = mu_msg_part_get_filename(part, FALSE))) { + const auto flat = Mu::utf8_flatten(fname); + g_free(fname); + add_term(pdata->_doc, file + flat); + } - maybe_index_text_part (msg, part, pdata); + maybe_index_text_part(msg, part, pdata); } - static void -add_terms_values_attach (Xapian::Document& doc, MuMsg *msg, - MuMsgFieldId mfid) +add_terms_values_attach(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - PartData pdata (doc, mfid); - mu_msg_part_foreach (msg, MU_MSG_OPTION_RECURSE_RFC822, - (MuMsgPartForeachFunc)each_part, &pdata); + PartData pdata(doc, mfid); + mu_msg_part_foreach(msg, + MU_MSG_OPTION_RECURSE_RFC822, + (MuMsgPartForeachFunc)each_part, + &pdata); } - static void -add_terms_values_body (Xapian::Document& doc, MuMsg *msg, - MuMsgFieldId mfid) +add_terms_values_body(Xapian::Document& doc, MuMsg* msg, MuMsgFieldId mfid) { - if (mu_msg_get_flags(msg) & MU_FLAG_ENCRYPTED) - return; /* ignore encrypted bodies */ + if (mu_msg_get_flags(msg) & MU_FLAG_ENCRYPTED) + return; /* ignore encrypted bodies */ - auto str = mu_msg_get_body_text (msg, MU_MSG_OPTION_NONE); - if (!str) /* FIXME: html->txt fallback needed */ - str = mu_msg_get_body_html (msg, MU_MSG_OPTION_NONE); - if (!str) - return; /* no body... */ + auto str = mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE); + if (!str) /* FIXME: html->txt fallback needed */ + str = mu_msg_get_body_html(msg, MU_MSG_OPTION_NONE); + if (!str) + return; /* no body... */ - Xapian::TermGenerator termgen; - termgen.set_document(doc); + Xapian::TermGenerator termgen; + termgen.set_document(doc); - const auto flat = Mu::utf8_flatten(str); - termgen.index_text (flat, 1, prefix(mfid)); + const auto flat = Mu::utf8_flatten(str); + termgen.index_text(flat, 1, prefix(mfid)); } struct MsgDoc { - Xapian::Document *_doc; - MuMsg *_msg; - Store::Private *_priv; - /* callback data, to determine whether this message is 'personal' */ - gboolean _personal; - const StringVec *_my_addresses; + Xapian::Document* _doc; + MuMsg* _msg; + Store::Private* _priv; + /* callback data, to determine whether this message is 'personal' */ + gboolean _personal; + const StringVec* _my_addresses; }; - static void -add_terms_values_default (MuMsgFieldId mfid, MsgDoc *msgdoc) +add_terms_values_default(MuMsgFieldId mfid, MsgDoc* msgdoc) { - if (mu_msg_field_is_numeric (mfid)) - add_terms_values_number - (*msgdoc->_doc, msgdoc->_msg, mfid); - else if (mu_msg_field_is_string (mfid)) - add_terms_values_string - (*msgdoc->_doc, msgdoc->_msg, mfid); - else if (mu_msg_field_is_string_list(mfid)) - add_terms_values_string_list - (*msgdoc->_doc, msgdoc->_msg, mfid); - else - g_return_if_reached (); + if (mu_msg_field_is_numeric(mfid)) + add_terms_values_number(*msgdoc->_doc, msgdoc->_msg, mfid); + else if (mu_msg_field_is_string(mfid)) + add_terms_values_string(*msgdoc->_doc, msgdoc->_msg, mfid); + else if (mu_msg_field_is_string_list(mfid)) + add_terms_values_string_list(*msgdoc->_doc, msgdoc->_msg, mfid); + else + g_return_if_reached(); } static void -add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc) +add_terms_values(MuMsgFieldId mfid, MsgDoc* msgdoc) { - /* note: contact-stuff (To/Cc/From) will handled in - * each_contact_info, not here */ - if (!mu_msg_field_xapian_index(mfid) && - !mu_msg_field_xapian_term(mfid) && - !mu_msg_field_xapian_value(mfid)) - return; + /* note: contact-stuff (To/Cc/From) will handled in + * each_contact_info, not here */ + if (!mu_msg_field_xapian_index(mfid) && !mu_msg_field_xapian_term(mfid) && + !mu_msg_field_xapian_value(mfid)) + return; - switch (mfid) { - case MU_MSG_FIELD_ID_DATE: - add_terms_values_date (*msgdoc->_doc, msgdoc->_msg, mfid); - break; - case MU_MSG_FIELD_ID_SIZE: - add_terms_values_size (*msgdoc->_doc, msgdoc->_msg, mfid); - break; - case MU_MSG_FIELD_ID_BODY_TEXT: - add_terms_values_body (*msgdoc->_doc, msgdoc->_msg, mfid); - break; - /* note: add_terms_values_attach handles _FILE, _MIME and - * _ATTACH_TEXT msgfields */ - case MU_MSG_FIELD_ID_FILE: - add_terms_values_attach (*msgdoc->_doc, msgdoc->_msg, mfid); - break; - case MU_MSG_FIELD_ID_MIME: - case MU_MSG_FIELD_ID_EMBEDDED_TEXT: - break; - case MU_MSG_FIELD_ID_THREAD_ID: - case MU_MSG_FIELD_ID_UID: - break; /* already taken care of elsewhere */ - default: - return add_terms_values_default (mfid, msgdoc); - } + switch (mfid) { + case MU_MSG_FIELD_ID_DATE: add_terms_values_date(*msgdoc->_doc, msgdoc->_msg, mfid); break; + case MU_MSG_FIELD_ID_SIZE: add_terms_values_size(*msgdoc->_doc, msgdoc->_msg, mfid); break; + case MU_MSG_FIELD_ID_BODY_TEXT: + add_terms_values_body(*msgdoc->_doc, msgdoc->_msg, mfid); + break; + /* note: add_terms_values_attach handles _FILE, _MIME and + * _ATTACH_TEXT msgfields */ + case MU_MSG_FIELD_ID_FILE: + add_terms_values_attach(*msgdoc->_doc, msgdoc->_msg, mfid); + break; + case MU_MSG_FIELD_ID_MIME: + case MU_MSG_FIELD_ID_EMBEDDED_TEXT: break; + case MU_MSG_FIELD_ID_THREAD_ID: + case MU_MSG_FIELD_ID_UID: break; /* already taken care of elsewhere */ + default: return add_terms_values_default(mfid, msgdoc); + } } - static const std::string& -xapian_pfx (MuMsgContact *contact) +xapian_pfx(MuMsgContact* contact) { - static const std::string empty; + static const std::string empty; - /* use ptr to string to prevent copy... */ - switch (contact->type) { - case MU_MSG_CONTACT_TYPE_TO: - return prefix(MU_MSG_FIELD_ID_TO); - case MU_MSG_CONTACT_TYPE_FROM: - return prefix(MU_MSG_FIELD_ID_FROM); - case MU_MSG_CONTACT_TYPE_CC: - return prefix(MU_MSG_FIELD_ID_CC); - case MU_MSG_CONTACT_TYPE_BCC: - return prefix(MU_MSG_FIELD_ID_BCC); - default: - g_warning ("unsupported contact type %u", - (unsigned)contact->type); - return empty; - } + /* use ptr to string to prevent copy... */ + switch (contact->type) { + case MU_MSG_CONTACT_TYPE_TO: return prefix(MU_MSG_FIELD_ID_TO); + case MU_MSG_CONTACT_TYPE_FROM: return prefix(MU_MSG_FIELD_ID_FROM); + case MU_MSG_CONTACT_TYPE_CC: return prefix(MU_MSG_FIELD_ID_CC); + case MU_MSG_CONTACT_TYPE_BCC: return prefix(MU_MSG_FIELD_ID_BCC); + default: g_warning("unsupported contact type %u", (unsigned)contact->type); return empty; + } } - static void -add_address_subfields (Xapian::Document& doc, const char *addr, - const std::string& pfx) +add_address_subfields(Xapian::Document& doc, const char* addr, const std::string& pfx) { - const char *at, *domain_part; - char *name_part; + const char *at, *domain_part; + char* name_part; - /* add "foo" and "bar.com" as terms as well for - * "foo@bar.com" */ - if (G_UNLIKELY(!(at = (g_strstr_len (addr, -1, "@"))))) - return; + /* add "foo" and "bar.com" as terms as well for + * "foo@bar.com" */ + if (G_UNLIKELY(!(at = (g_strstr_len(addr, -1, "@"))))) + return; - name_part = g_strndup(addr, at - addr); // foo - domain_part = at + 1; + name_part = g_strndup(addr, at - addr); // foo + domain_part = at + 1; - add_term(doc, pfx + name_part); - add_term(doc, pfx + domain_part); + add_term(doc, pfx + name_part); + add_term(doc, pfx + domain_part); - g_free (name_part); + g_free(name_part); } static gboolean -each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc) +each_contact_info(MuMsgContact* contact, MsgDoc* msgdoc) { - /* for now, don't store reply-to addresses */ - if (mu_msg_contact_type (contact) == MU_MSG_CONTACT_TYPE_REPLY_TO) - return TRUE; + /* for now, don't store reply-to addresses */ + if (mu_msg_contact_type(contact) == MU_MSG_CONTACT_TYPE_REPLY_TO) + return TRUE; - const std::string pfx (xapian_pfx(contact)); - if (pfx.empty()) - return TRUE; /* unsupported contact type */ + const std::string pfx(xapian_pfx(contact)); + if (pfx.empty()) + return TRUE; /* unsupported contact type */ - if (!mu_str_is_empty(contact->name)) { - Xapian::TermGenerator termgen; - termgen.set_document (*msgdoc->_doc); - const auto flat = Mu::utf8_flatten(contact->name); - termgen.index_text (flat, 1, pfx); - } + if (!mu_str_is_empty(contact->name)) { + Xapian::TermGenerator termgen; + termgen.set_document(*msgdoc->_doc); + const auto flat = Mu::utf8_flatten(contact->name); + termgen.index_text(flat, 1, pfx); + } - if (!mu_str_is_empty(contact->email)) { - const auto flat = Mu::utf8_flatten(contact->email); - add_term(*msgdoc->_doc, pfx + flat); - add_address_subfields (*msgdoc->_doc, contact->email, pfx); - /* store it also in our contacts cache */ - auto& contacts{msgdoc->_priv->contacts_}; - contacts.add(Mu::ContactInfo(contact->full_address, - contact->email, - contact->name ? contact->name : "", - msgdoc->_personal, - mu_msg_get_date(msgdoc->_msg))); - } + if (!mu_str_is_empty(contact->email)) { + const auto flat = Mu::utf8_flatten(contact->email); + add_term(*msgdoc->_doc, pfx + flat); + add_address_subfields(*msgdoc->_doc, contact->email, pfx); + /* store it also in our contacts cache */ + auto& contacts{msgdoc->_priv->contacts_}; + contacts.add(Mu::ContactInfo(contact->full_address, + contact->email, + contact->name ? contact->name : "", + msgdoc->_personal, + mu_msg_get_date(msgdoc->_msg))); + } - return TRUE; + return TRUE; } Xapian::Document -Store::Private::new_doc_from_message (MuMsg *msg) +Store::Private::new_doc_from_message(MuMsg* msg) { - Xapian::Document doc; - MsgDoc docinfo = {&doc, msg, this, 0, NULL}; + Xapian::Document doc; + MsgDoc docinfo = {&doc, msg, this, 0, NULL}; - mu_msg_field_foreach ((MuMsgFieldForeachFunc)add_terms_values, &docinfo); + mu_msg_field_foreach((MuMsgFieldForeachFunc)add_terms_values, &docinfo); - mu_msg_contact_foreach - (msg, [](auto contact, gpointer msgdocptr)->gboolean { - auto msgdoc{reinterpret_cast(msgdocptr)}; + mu_msg_contact_foreach( + msg, + [](auto contact, gpointer msgdocptr) -> gboolean { + auto msgdoc{reinterpret_cast(msgdocptr)}; - if (!contact->email) - return FALSE; // invalid contact - else if (msgdoc->_personal) - return TRUE; // already deemed personal + if (!contact->email) + return FALSE; // invalid contact + else if (msgdoc->_personal) + return TRUE; // already deemed personal - if (msgdoc->_priv->contacts_.is_personal(contact->email)) - msgdoc->_personal = true; // this one's personal. + if (msgdoc->_priv->contacts_.is_personal(contact->email)) + msgdoc->_personal = true; // this one's personal. - return TRUE; - }, &docinfo); + return TRUE; + }, + &docinfo); - /* also store the contact-info as separate terms, and add it - * to the cache */ - mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_info, - &docinfo); + /* also store the contact-info as separate terms, and add it + * to the cache */ + mu_msg_contact_foreach(msg, (MuMsgContactForeachFunc)each_contact_info, &docinfo); - // g_printerr ("\n--%s\n--\n", doc.serialise().c_str()); + // g_printerr ("\n--%s\n--\n", doc.serialise().c_str()); - return doc; + return doc; } static void -update_threading_info (MuMsg *msg, Xapian::Document& doc) +update_threading_info(MuMsg* msg, Xapian::Document& doc) { - const GSList *refs; + const GSList* refs; - // refs contains a list of parent messages, with the oldest - // one first until the last one, which is the direct parent of - // the current message. of course, it may be empty. - // - // NOTE: there may be cases where the list is truncated; we happily - // ignore that case. - refs = mu_msg_get_references (msg); + // refs contains a list of parent messages, with the oldest + // one first until the last one, which is the direct parent of + // the current message. of course, it may be empty. + // + // NOTE: there may be cases where the list is truncated; we happily + // ignore that case. + refs = mu_msg_get_references(msg); - char thread_id[16+1]; - hash_str(thread_id, sizeof(thread_id), - refs ? (const char*)refs->data : mu_msg_get_msgid (msg)); + char thread_id[16 + 1]; + hash_str(thread_id, + sizeof(thread_id), + refs ? (const char*)refs->data : mu_msg_get_msgid(msg)); - add_term (doc, prefix(MU_MSG_FIELD_ID_THREAD_ID) + thread_id); - doc.add_value((Xapian::valueno)MU_MSG_FIELD_ID_THREAD_ID, thread_id); + add_term(doc, prefix(MU_MSG_FIELD_ID_THREAD_ID) + thread_id); + doc.add_value((Xapian::valueno)MU_MSG_FIELD_ID_THREAD_ID, thread_id); } - Xapian::docid -Store::Private::add_or_update_msg (unsigned docid, MuMsg *msg, GError **err) +Store::Private::add_or_update_msg(unsigned docid, MuMsg* msg) { - g_return_val_if_fail (msg, InvalidId); + g_return_val_if_fail(msg, InvalidId); - try { - Xapian::Document doc (new_doc_from_message(msg)); - const std::string term (get_uid_term (mu_msg_get_path(msg))); + return xapian_try( + [&] { + Xapian::Document doc(new_doc_from_message(msg)); + const std::string term(get_uid_term(mu_msg_get_path(msg))); - add_term (doc, term); + add_term(doc, term); - // update the threading info if this message has a message id - if (mu_msg_get_msgid (msg)) - update_threading_info (msg, doc); + // update the threading info if this message has a message id + if (mu_msg_get_msgid(msg)) + update_threading_info(msg, doc); + if (docid == 0) + return writable_db().replace_document(term, doc); - if (docid == 0) - return writable_db().replace_document (term, doc); - - writable_db().replace_document (docid, doc); - return docid; - - } MU_XAPIAN_CATCH_BLOCK_G_ERROR (err, MU_ERROR_XAPIAN_STORE_FAILED); - - return InvalidId; + writable_db().replace_document(docid, doc); + return docid; + }, + InvalidId); } diff --git a/lib/mu-store.hh b/lib/mu-store.hh index 645d8c62..83b22447 100644 --- a/lib/mu-store.hh +++ b/lib/mu-store.hh @@ -27,7 +27,6 @@ #include #include - #include "mu-contacts.hh" #include @@ -36,267 +35,273 @@ namespace Mu { class Store { -public: - using Id = Xapian::docid; /**< Id for a message in the store */ - static constexpr Id InvalidId = 0; /**< Invalid store id */ + public: + using Id = Xapian::docid; /**< Id for a message in the store */ + static constexpr Id InvalidId = 0; /**< Invalid store id */ - static constexpr size_t MaxTermLength = 240; /**< Maximum length of a term, - http://article.gmane.org/gmane.comp.search.xapian.general/3656 */ + static constexpr size_t MaxTermLength = 240; /**< Maximum length of a term, + http://article.gmane.org/gmane.comp.search.xapian.general/3656 */ - /** - * Construct a store for an existing document database - * - * @param path path to the database - * @param readonly whether to open the database in read-only mode - */ - Store (const std::string& path, bool readonly=true); + /** + * Construct a store for an existing document database + * + * @param path path to the database + * @param readonly whether to open the database in read-only mode + */ + Store(const std::string& path, bool readonly = true); - struct Config { - size_t max_message_size{}; - /**< maximum size (in bytes) for a message, or 0 for default */ - size_t batch_size{}; - /**< size of batches before committing, or 0 for default */ - }; + struct Config { + size_t max_message_size{}; + /**< maximum size (in bytes) for a message, or 0 for default */ + size_t batch_size{}; + /**< size of batches before committing, or 0 for default */ + }; - /** - * Construct a store for a not-yet-existing document database - * - * @param path path to the database - * @param maildir maildir to use for this store - * @param personal_addresses addresses that should be recognized as - * 'personal' for identifying personal messages. - */ - Store (const std::string& path, const std::string& maildir, - const StringVec& personal_addresses, const Config& conf); + /** + * Construct a store for a not-yet-existing document database + * + * @param path path to the database + * @param maildir maildir to use for this store + * @param personal_addresses addresses that should be recognized as + * 'personal' for identifying personal messages. + */ + Store(const std::string& path, + const std::string& maildir, + const StringVec& personal_addresses, + const Config& conf); - /** - * Construct an in-memory, writeable store for testing - * - * @param maildir maildir to use for this store - * @param personal_addresses addresses that should be recognized as - * 'personal' for identifying personal messages. - */ - Store (const std::string& maildir, - const StringVec& personal_addresses, const Config& conf); + /** + * Construct an in-memory, writeable store for testing + * + * @param maildir maildir to use for this store + * @param personal_addresses addresses that should be recognized as + * 'personal' for identifying personal messages. + */ + Store(const std::string& maildir, const StringVec& personal_addresses, const Config& conf); - /** - * DTOR - */ - ~Store(); + /** + * DTOR + */ + ~Store(); - struct Metadata { - std::string database_path; /**< Full path to the Xapian database */ - std::string schema_version; /**< Database schema version */ - std::time_t created; /**< database creation time */ + struct Metadata { + std::string database_path; /**< Full path to the Xapian database */ + std::string schema_version; /**< Database schema version */ + std::time_t created; /**< database creation time */ - bool read_only; /**< Is the database opened read-only? */ - size_t batch_size; /**< Maximum database transaction batch size */ - bool in_memory; /**< Is this an in-memory database (for testing)?*/ + bool read_only; /**< Is the database opened read-only? */ + size_t batch_size; /**< Maximum database transaction batch size */ + bool in_memory; /**< Is this an in-memory database (for testing)?*/ - std::string root_maildir; /**< Absolute path to the top-level maildir */ + std::string root_maildir; /**< Absolute path to the top-level maildir */ - StringVec personal_addresses; /**< Personal e-mail addresses */ - size_t max_message_size; /**< Maximus allowed message size */ - }; + StringVec personal_addresses; /**< Personal e-mail addresses */ + size_t max_message_size; /**< Maximus allowed message size */ + }; - /** - * Get metadata about this store. - * - * @return the metadata - */ - const Metadata& metadata() const; - /** - * Get the Contacts object for this store - * - * @return the Contacts object - */ - const Contacts& contacts() const; + /** + * Get metadata about this store. + * + * @return the metadata + */ + const Metadata& metadata() const; + /** + * Get the Contacts object for this store + * + * @return the Contacts object + */ + const Contacts& contacts() const; + /** + * Get the underlying Xapian database for this store. + * + * @return the database + */ + const Xapian::Database& database() const; - /** - * Get the underlying Xapian database for this store. - * - * @return the database - */ - const Xapian::Database& database() const; + /** + * Get the underlying writable Xapian database for this + * store. Throws is this store is not writable. + * + * @return the writable database + */ + Xapian::WritableDatabase& writable_database(); - /** - * Get the underlying writable Xapian database for this - * store. Throws is this store is not writable. - * - * @return the writable database - */ - Xapian::WritableDatabase& writable_database(); + /** + * Get the Indexer associated with this store. It is an error to call + * this on a read-only store. + * + * @return the indexer. + */ + Indexer& indexer(); - /** - * Get the Indexer associated with this store. It is an error to call - * this on a read-only store. - * - * @return the indexer. - */ - Indexer& indexer(); + /** + * Add a message to the store. + * + * @param path the message path. + * + * @return the doc id of the added message + */ + Id add_message(const std::string& path); - /** - * Add a message to the store. - * - * @param path the message path. - * - * @return the doc id of the added message - */ - Id add_message (const std::string& path); + /** + * Update a message in the store. + * + * @param msg a message + * @param id the id for this message + * + * @return false in case of failure; true otherwise. + */ + bool update_message(MuMsg* msg, Id id); - /** - * Update a message in the store. - * - * @param msg a message - * @param id the id for this message - * - * @return false in case of failure; true otherwise. - */ - bool update_message (MuMsg *msg, Id id); + /** + * Remove a message from the store. It will _not_ remove the message + * fromt he file system. + * + * @param path the message path. + * + * @return true if removing happened; false otherwise. + */ + bool remove_message(const std::string& path); - /** - * Remove a message from the store. It will _not_ remove the message - * fromt he file system. - * - * @param path the message path. - * - * @return true if removing happened; false otherwise. - */ - bool remove_message (const std::string& path); + /** + * Remove a number if messages from the store. It will _not_ remove the + * message fromt he file system. + * + * @param ids vector with store ids for the message + */ + void remove_messages(const std::vector& ids); - /** - * Remove a number if messages from the store. It will _not_ remove the - * message fromt he file system. - * - * @param ids vector with store ids for the message - */ - void remove_messages (const std::vector& ids); + /** + * Remove a message from the store. It will _not_ remove the message + * fromt he file system. + * + * @param id the store id for the message + */ + void remove_message(Id id) { remove_messages({id}); } - /** - * Remove a message from the store. It will _not_ remove the message - * fromt he file system. - * - * @param id the store id for the message - */ - void remove_message (Id id) { remove_messages({id}); } + /** + * Find message in the store. + * + * @param id doc id for the message to find + * + * @return a message (owned by caller), or nullptr + */ + MuMsg* find_message(Id id) const; - /** - * Find message in the store. - * - * @param id doc id for the message to find - * - * @return a message (owned by caller), or nullptr - */ - MuMsg* find_message (Id id) const; + /** + * does a certain message exist in the store already? + * + * @param path the message path + * + * @return true if the message exists in the store, false otherwise + */ + bool contains_message(const std::string& path) const; - /** - * does a certain message exist in the store already? - * - * @param path the message path - * - * @return true if the message exists in the store, false otherwise - */ - bool contains_message (const std::string& path) const; + /** + * Prototype for the ForEachMessageFunc + * + * @param id :t store Id for the message + * @param path: the absolute path to the message + * + * @return true if for_each should continue; false to quit + */ + using ForEachMessageFunc = std::function; - /** - * Prototype for the ForEachMessageFunc - * - * @param id :t store Id for the message - * @param path: the absolute path to the message - * - * @return true if for_each should continue; false to quit - */ - using ForEachMessageFunc = std::function; + /** + * Call @param func for each document in the store. This takes a lock on + * the store, so the func should _not_ call any other Store:: methods. + * + * @param func a Callable invoked for each message. + * + * @return the number of times func was invoked + */ + size_t for_each_message_path(ForEachMessageFunc func) const; - /** - * Call @param func for each document in the store. This takes a lock on - * the store, so the func should _not_ call any other Store:: methods. - * - * @param func a Callable invoked for each message. - * - * @return the number of times func was invoked - */ - size_t for_each_message_path (ForEachMessageFunc func) const; + /** + * Prototype for the ForEachTermFunc + * + * @param term: + * + * @return true if for_each should continue; false to quit + */ + using ForEachTermFunc = std::function; - /** - * Prototype for the ForEachTermFunc - * - * @param term: - * - * @return true if for_each should continue; false to quit - */ - using ForEachTermFunc = std::function; + /** + * Call @param func for each term for the given field in the store. This + * takes a lock on the store, so the func should _not_ call any other + * Store:: methods. + * + * @param func a Callable invoked for each message. + * + * @return the number of times func was invoked + */ + size_t for_each_term(const std::string& field, ForEachTermFunc func) const; - /** - * Call @param func for each term for the given field in the store. This - * takes a lock on the store, so the func should _not_ call any other - * Store:: methods. - * - * @param func a Callable invoked for each message. - * - * @return the number of times func was invoked - */ - size_t for_each_term (const std::string& field, ForEachTermFunc func) const; + /** + * Get the timestamp for some message, or 0 if not found + * + * @param path the path + * + * @return the timestamp, or 0 if not found + */ + time_t message_tstamp(const std::string& path) const; - /** - * Get the timestamp for some message, or 0 if not found - * - * @param path the path - * - * @return the timestamp, or 0 if not found - */ - time_t message_tstamp (const std::string& path) const; + /** + * Get the timestamp for some directory + * + * @param path the path + * + * @return the timestamp, or 0 if not found + */ + time_t dirstamp(const std::string& path) const; - /** - * Get the timestamp for some directory - * - * @param path the path - * - * @return the timestamp, or 0 if not found - */ - time_t dirstamp (const std::string& path) const; + /** + * Set the timestamp for some directory + * + * @param path a filesystem path + * @param tstamp the timestamp for that path + */ + void set_dirstamp(const std::string& path, time_t tstamp); - /** - * Set the timestamp for some directory - * - * @param path a filesystem path - * @param tstamp the timestamp for that path - */ - void set_dirstamp (const std::string& path, time_t tstamp); + /** + * Get the number of documents in the document database + * + * @return the number + */ + std::size_t size() const; - /** - * Get the number of documents in the document database - * - * @return the number - */ - std::size_t size() const; + /** + * Is the database empty? + * + * @return true or false + */ + bool empty() const; - /** - * Is the database empty? - * - * @return true or false - */ - bool empty() const; + /** + * Start a Xapian transaction, opportunistically. If a transaction + * is already underway, do nothing. + */ + void begin_transaction(); - /** - * Commit the current group of modifications (i.e., transaction) to disk; - * This rarely needs to be called explicitly, as Store will take care of - * it. - */ - void commit(); + /** + * Commit the current group of modifications (i.e., transaction) to + * disk, opportunistically. If no transaction is underway, do + * nothing. + */ + void commit_transaction(); - /** - * Get a reference to the private data. For internal use. - * - * @return private reference. - */ - struct Private; - std::unique_ptr& priv() { return priv_; } - const std::unique_ptr& priv() const { return priv_; } + /** + * Get a reference to the private data. For internal use. + * + * @return private reference. + */ + struct Private; + std::unique_ptr& priv() { return priv_; } + const std::unique_ptr& priv() const { return priv_; } -private: - std::unique_ptr priv_; + private: + std::unique_ptr priv_; }; } // namespace Mu diff --git a/lib/mu-tokenizer.cc b/lib/mu-tokenizer.cc index f314d049..14b318b5 100644 --- a/lib/mu-tokenizer.cc +++ b/lib/mu-tokenizer.cc @@ -27,18 +27,17 @@ using namespace Mu; static bool -is_separator (char c) +is_separator(char c) { if (isblank(c)) return true; - const auto seps = std::string ("()"); + const auto seps = std::string("()"); return seps.find(c) != std::string::npos; } - static Mu::Token -op_or_value (size_t pos, const std::string& val) +op_or_value(size_t pos, const std::string& val) { auto s = val; std::transform(s.begin(), s.end(), s.begin(), ::tolower); @@ -56,21 +55,20 @@ op_or_value (size_t pos, const std::string& val) } static void -unread_char (std::string& food, char kar, size_t& pos) +unread_char(std::string& food, char kar, size_t& pos) { food = kar + food; --pos; } static Mu::Token -eat_token (std::string& food, size_t& pos) +eat_token(std::string& food, size_t& pos) { - bool quoted{}; - bool escaped{}; - std::string value {}; + bool quoted{}; + bool escaped{}; + std::string value{}; while (!food.empty()) { - const auto kar = food[0]; food.erase(0, 1); ++pos; @@ -91,9 +89,8 @@ eat_token (std::string& food, size_t& pos) } if (!quoted && !escaped && is_separator(kar)) { - if (!value.empty() && kar != ':') { - unread_char (food, kar, pos); + unread_char(food, kar, pos); return op_or_value(pos, value); } @@ -102,32 +99,31 @@ eat_token (std::string& food, size_t& pos) switch (kar) { case '(': return {pos, Token::Type::Open, "("}; - case ')': return {pos, Token::Type::Close,")"}; + case ')': return {pos, Token::Type::Close, ")"}; default: break; } } - value += kar; - escaped = false; + value += kar; + escaped = false; } return {pos, Token::Type::Data, value}; } - Mu::Tokens -Mu::tokenize (const std::string& s) +Mu::tokenize(const std::string& s) { Tokens tokens{}; std::string food = utf8_clean(s); - size_t pos{0}; + size_t pos{0}; if (s.empty()) return {}; while (!food.empty()) - tokens.emplace_back(eat_token (food, pos)); + tokens.emplace_back(eat_token(food, pos)); return tokens; } diff --git a/lib/mu-tokenizer.hh b/lib/mu-tokenizer.hh index aa56d896..7016e8b7 100644 --- a/lib/mu-tokenizer.hh +++ b/lib/mu-tokenizer.hh @@ -41,26 +41,26 @@ namespace Mu { // A token struct Token { enum class Type { - Data, /**< e .g., banana or date:..456 */ + Data, /**< e .g., banana or date:..456 */ // Brackets - Open, /**< ( */ - Close, /**< ) */ + Open, /**< ( */ + Close, /**< ) */ // Unops - Not, /**< logical not*/ + Not, /**< logical not*/ // Binops - And, /**< logical and */ - Or, /**< logical not */ - Xor, /**< logical xor */ + And, /**< logical and */ + Or, /**< logical not */ + Xor, /**< logical xor */ - Empty, /**< nothing */ + Empty, /**< nothing */ }; - size_t pos{}; /**< position in string */ - Type type{}; /**< token type */ - const std::string str{}; /**< data for this token */ + size_t pos{}; /**< position in string */ + Type type{}; /**< token type */ + const std::string str{}; /**< data for this token */ /** * operator== @@ -69,10 +69,9 @@ struct Token { * * @return true if rhs is equal to this; false otherwise */ - bool operator==(const Token& rhs) const { - return pos == rhs.pos && - type == rhs.type && - str == rhs.str; + bool operator==(const Token& rhs) const + { + return pos == rhs.pos && type == rhs.type && str == rhs.str; } }; @@ -85,21 +84,21 @@ struct Token { * @return the updated output stream */ inline std::ostream& -operator<< (std::ostream& os, Token::Type t) +operator<<(std::ostream& os, Token::Type t) { - switch (t) { - case Token::Type::Data: os << ""; break; + switch (t) { + case Token::Type::Data: os << ""; break; - case Token::Type::Open: os << ""; break; - case Token::Type::Close: os << "";break; + case Token::Type::Open: os << ""; break; + case Token::Type::Close: os << ""; break; - case Token::Type::Not: os << ""; break; - case Token::Type::And: os << ""; break; - case Token::Type::Or: os << ""; break; - case Token::Type::Xor: os << ""; break; - case Token::Type::Empty: os << ""; break; - default: // can't happen, but pacify compiler - throw std::runtime_error ("<>"); + case Token::Type::Not: os << ""; break; + case Token::Type::And: os << ""; break; + case Token::Type::Or: os << ""; break; + case Token::Type::Xor: os << ""; break; + case Token::Type::Empty: os << ""; break; + default: // can't happen, but pacify compiler + throw std::runtime_error("<>"); } return os; @@ -114,7 +113,7 @@ operator<< (std::ostream& os, Token::Type t) * @return the updated output stream */ inline std::ostream& -operator<< (std::ostream& os, const Token& t) +operator<<(std::ostream& os, const Token& t) { os << t.pos << ": " << t.type; @@ -133,7 +132,7 @@ operator<< (std::ostream& os, const Token& t) * @return a deque of tokens */ using Tokens = std::deque; -Tokens tokenize (const std::string& s); +Tokens tokenize(const std::string& s); } // namespace Mu diff --git a/lib/mu-tree.hh b/lib/mu-tree.hh index 70642a17..b5724be6 100644 --- a/lib/mu-tree.hh +++ b/lib/mu-tree.hh @@ -43,40 +43,40 @@ struct Node { Invalid }; - Node(Type _type, std::unique_ptr&& _data): - type{_type}, data{std::move(_data)} {} - Node(Type _type): type{_type} {} + Node(Type _type, std::unique_ptr&& _data) : type{_type}, data{std::move(_data)} {} + Node(Type _type) : type{_type} {} Node(Node&& rhs) = default; - Type type; - std::unique_ptr data; + Type type; + std::unique_ptr data; - static const char* type_name (Type t) { + static const char* type_name(Type t) + { switch (t) { - case Type::Empty: return ""; break; - case Type::OpAnd: return "and"; break; - case Type::OpOr: return "or"; break; - case Type::OpXor: return "xor"; break; + case Type::Empty: return ""; break; + case Type::OpAnd: return "and"; break; + case Type::OpOr: return "or"; break; + case Type::OpXor: return "xor"; break; case Type::OpAndNot: return "andnot"; break; - case Type::OpNot: return "not"; break; - case Type::Value: return "value"; break; - case Type::Range: return "range"; break; - case Type::Invalid: return ""; break; - default: - throw Mu::Error(Error::Code::Internal, "unexpected type"); + case Type::OpNot: return "not"; break; + case Type::Value: return "value"; break; + case Type::Range: return "range"; break; + case Type::Invalid: return ""; break; + default: throw Mu::Error(Error::Code::Internal, "unexpected type"); } } - static constexpr bool is_binop(Type t) { - return t == Type::OpAnd || t == Type::OpAndNot || - t == Type::OpOr || t == Type::OpXor; + static constexpr bool is_binop(Type t) + { + return t == Type::OpAnd || t == Type::OpAndNot || t == Type::OpOr || + t == Type::OpXor; } }; inline std::ostream& -operator<< (std::ostream& os, const Node& t) +operator<<(std::ostream& os, const Node& t) { - os << Node::type_name(t.type); + os << Node::type_name(t.type); if (t.data) os << t.data; @@ -84,18 +84,18 @@ operator<< (std::ostream& os, const Node& t) } struct Tree { - Tree(Node&& _node): node(std::move(_node)) {} + Tree(Node&& _node) : node(std::move(_node)) {} Tree(Tree&& rhs) = default; - void add_child (Tree&& child) { children.emplace_back(std::move(child)); } + void add_child(Tree&& child) { children.emplace_back(std::move(child)); } bool empty() const { return node.type == Node::Type::Empty; } - Node node; - std::vector children; + Node node; + std::vector children; }; inline std::ostream& -operator<< (std::ostream& os, const Tree& tree) +operator<<(std::ostream& os, const Tree& tree) { os << '(' << tree.node; for (const auto& subtree : tree.children) @@ -107,5 +107,4 @@ operator<< (std::ostream& os, const Tree& tree) } // namespace Mu - #endif /* TREE_HH__ */ diff --git a/lib/mu-xapian.cc b/lib/mu-xapian.cc index f620c4fa..733bb40e 100644 --- a/lib/mu-xapian.cc +++ b/lib/mu-xapian.cc @@ -28,94 +28,91 @@ using namespace Mu; static Xapian::Query -xapian_query_op (const Mu::Tree& tree) +xapian_query_op(const Mu::Tree& tree) { Xapian::Query::op op; #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (tree.node.type) { case Node::Type::OpNot: // OpNot x ::= AND NOT x - if (tree.children.size() != 1) - throw std::runtime_error ("invalid # of children"); - return Xapian::Query (Xapian::Query::OP_AND_NOT, - Xapian::Query::MatchAll, - xapian_query(tree.children.front())); - case Node::Type::OpAnd: op = Xapian::Query::OP_AND; break; - case Node::Type::OpOr: op = Xapian::Query::OP_OR; break; - case Node::Type::OpXor: op = Xapian::Query::OP_XOR; break; + if (tree.children.size() != 1) + throw std::runtime_error("invalid # of children"); + return Xapian::Query(Xapian::Query::OP_AND_NOT, + Xapian::Query::MatchAll, + xapian_query(tree.children.front())); + case Node::Type::OpAnd: op = Xapian::Query::OP_AND; break; + case Node::Type::OpOr: op = Xapian::Query::OP_OR; break; + case Node::Type::OpXor: op = Xapian::Query::OP_XOR; break; case Node::Type::OpAndNot: op = Xapian::Query::OP_AND_NOT; break; - default: throw Mu::Error (Error::Code::Internal, "invalid op"); // bug + default: throw Mu::Error(Error::Code::Internal, "invalid op"); // bug } #pragma GCC diagnostic pop std::vector childvec; - for (const auto& subtree: tree.children) + for (const auto& subtree : tree.children) childvec.emplace_back(xapian_query(subtree)); return Xapian::Query(op, childvec.begin(), childvec.end()); } static Xapian::Query -make_query (const Value* val, const std::string& str, bool maybe_wildcard) +make_query(const Value* val, const std::string& str, bool maybe_wildcard) { const auto vlen{str.length()}; if (!maybe_wildcard || vlen <= 1 || str[vlen - 1] != '*') return Xapian::Query(val->prefix + str); else return Xapian::Query(Xapian::Query::OP_WILDCARD, - val->prefix + str.substr(0, vlen - 1)); + val->prefix + str.substr(0, vlen - 1)); } static Xapian::Query -xapian_query_value (const Mu::Tree& tree) +xapian_query_value(const Mu::Tree& tree) { - const auto v = dynamic_cast (tree.node.data.get()); + const auto v = dynamic_cast(tree.node.data.get()); if (!v->phrase) - return make_query(v, v->value, true/*maybe-wildcard*/); + return make_query(v, v->value, true /*maybe-wildcard*/); - const auto parts = split (v->value, " "); + const auto parts = split(v->value, " "); if (parts.empty()) return Xapian::Query::MatchNothing; // shouldn't happen if (parts.size() == 1) - return make_query(v, parts.front(), true/*maybe-wildcard*/); + return make_query(v, parts.front(), true /*maybe-wildcard*/); std::vector phvec; - for (const auto& p: parts) - phvec.emplace_back(make_query(v, p, false/*no wildcards*/)); + for (const auto& p : parts) + phvec.emplace_back(make_query(v, p, false /*no wildcards*/)); - return Xapian::Query (Xapian::Query::OP_PHRASE, phvec.begin(), phvec.end()); + return Xapian::Query(Xapian::Query::OP_PHRASE, phvec.begin(), phvec.end()); } static Xapian::Query -xapian_query_range (const Mu::Tree& tree) +xapian_query_range(const Mu::Tree& tree) { - const auto r { dynamic_cast(tree.node.data.get()) }; + const auto r{dynamic_cast(tree.node.data.get())}; - return Xapian::Query(Xapian::Query::OP_VALUE_RANGE, (Xapian::valueno)r->id, - r->lower, r->upper); + return Xapian::Query(Xapian::Query::OP_VALUE_RANGE, + (Xapian::valueno)r->id, + r->lower, + r->upper); } Xapian::Query -Mu::xapian_query (const Mu::Tree& tree) +Mu::xapian_query(const Mu::Tree& tree) { #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-enum" switch (tree.node.type) { - case Node::Type::Empty: - return Xapian::Query(); + case Node::Type::Empty: return Xapian::Query(); case Node::Type::OpNot: case Node::Type::OpAnd: case Node::Type::OpOr: case Node::Type::OpXor: - case Node::Type::OpAndNot: - return xapian_query_op (tree); - case Node::Type::Value: - return xapian_query_value (tree); - case Node::Type::Range: - return xapian_query_range (tree); - default: - throw Mu::Error (Error::Code::Internal, "invalid query"); // bug + case Node::Type::OpAndNot: return xapian_query_op(tree); + case Node::Type::Value: return xapian_query_value(tree); + case Node::Type::Range: return xapian_query_range(tree); + default: throw Mu::Error(Error::Code::Internal, "invalid query"); // bug } #pragma GCC diagnostic pop } diff --git a/lib/mu-xapian.hh b/lib/mu-xapian.hh index 95be0576..045ab31a 100644 --- a/lib/mu-xapian.hh +++ b/lib/mu-xapian.hh @@ -17,7 +17,6 @@ ** 02110-1301, USA. */ - #ifndef __XAPIAN_HH__ #define __XAPIAN_HH__ @@ -33,7 +32,7 @@ namespace Mu { * * @return a Xapian query object */ -Xapian::Query xapian_query (const Mu::Tree& tree); +Xapian::Query xapian_query(const Mu::Tree& tree); } // namespace Mu diff --git a/lib/test-indexer.cc b/lib/test-indexer.cc index 3660381f..32e9ea39 100644 --- a/lib/test-indexer.cc +++ b/lib/test-indexer.cc @@ -31,40 +31,39 @@ using namespace Mu; static void -test_index_maildir () +test_index_maildir() { - allow_warnings(); + allow_warnings(); - Store store{test_mu_common_get_random_tmpdir(), std::string{MU_TESTMAILDIR}}; + Store store{test_mu_common_get_random_tmpdir(), std::string{MU_TESTMAILDIR}}; Indexer idx{Indexer::Config{}, store}; - g_assert_true (idx.start()); - while (idx.is_running()) { - sleep(1); - } + g_assert_true(idx.start()); + while (idx.is_running()) { + sleep(1); + } - g_print ("again!\n"); + g_print("again!\n"); - g_assert_true (idx.start()); - while (idx.is_running()) { - sleep(1); - } + g_assert_true(idx.start()); + while (idx.is_running()) { + sleep(1); + } } int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/indexer/index-maildir", test_index_maildir); - - return g_test_run (); + g_test_add_func("/indexer/index-maildir", test_index_maildir); + return g_test_run(); } catch (const std::runtime_error& re) { std::cerr << re.what() << "\n"; return 1; } catch (...) { - std::cerr << "caught exception\n"; - return 1; + std::cerr << "caught exception\n"; + return 1; } diff --git a/lib/test-mu-common.cc b/lib/test-mu-common.cc index 6e4d159f..92d706f5 100644 --- a/lib/test-mu-common.cc +++ b/lib/test-mu-common.cc @@ -34,60 +34,56 @@ #include "test-mu-common.hh" char* -test_mu_common_get_random_tmpdir (void) +test_mu_common_get_random_tmpdir(void) { - char*dir; - int res; + char* dir; + int res; - dir = g_strdup_printf ( - "%s%cmu-test-%d%ctest-%x", - g_get_tmp_dir(), - G_DIR_SEPARATOR, - getuid(), - G_DIR_SEPARATOR, - (int)random()*getpid()*(int)time(NULL)); + dir = g_strdup_printf("%s%cmu-test-%d%ctest-%x", + g_get_tmp_dir(), + G_DIR_SEPARATOR, + getuid(), + G_DIR_SEPARATOR, + (int)random() * getpid() * (int)time(NULL)); - res = g_mkdir_with_parents (dir, 0700); - g_assert (res != -1); + res = g_mkdir_with_parents(dir, 0700); + g_assert(res != -1); return dir; } - const char* -set_tz (const char* tz) +set_tz(const char* tz) { static const char* oldtz; - oldtz = getenv ("TZ"); + oldtz = getenv("TZ"); if (tz) - setenv ("TZ", tz, 1); + setenv("TZ", tz, 1); else - unsetenv ("TZ"); + unsetenv("TZ"); - tzset (); + tzset(); return oldtz; } - gboolean -set_en_us_utf8_locale (void) +set_en_us_utf8_locale(void) { - setenv ("LC_ALL", "en_US.UTF-8", 1); - setlocale (LC_ALL, "en_US.UTF-8"); + setenv("LC_ALL", "en_US.UTF-8", 1); + setlocale(LC_ALL, "en_US.UTF-8"); - if (strcmp (nl_langinfo(CODESET), "UTF-8") != 0) { - g_print ("Note: Unit tests require the en_US.utf8 locale. " - "Ignoring test cases.\n"); + if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) { + g_print("Note: Unit tests require the en_US.utf8 locale. " + "Ignoring test cases.\n"); return FALSE; } return TRUE; } - void -black_hole (void) +black_hole(void) { return; /* do nothing */ } diff --git a/lib/test-mu-common.hh b/lib/test-mu-common.hh index 31f4d3a9..cfb427f9 100644 --- a/lib/test-mu-common.hh +++ b/lib/test-mu-common.hh @@ -29,15 +29,13 @@ G_BEGIN_DECLS * * @return a random dir name, g_free when it's no longer needed */ -char* test_mu_common_get_random_tmpdir (void); - - +char* test_mu_common_get_random_tmpdir(void); /** * set the output to /dev/null * */ -void black_hole (void); +void black_hole(void); /** * set the timezone @@ -46,15 +44,14 @@ void black_hole (void); * * @return the old timezone */ -const char* set_tz (const char* tz); - +const char* set_tz(const char* tz); /** * switch the locale to en_US.utf8, return TRUE if it succeeds * * @return TRUE if the switch succeeds, FALSE otherwise */ -gboolean set_en_us_utf8_locale (void); +gboolean set_en_us_utf8_locale(void); G_END_DECLS diff --git a/lib/test-mu-container.cc b/lib/test-mu-container.cc index 6f61f1de..925de1a0 100644 --- a/lib/test-mu-container.cc +++ b/lib/test-mu-container.cc @@ -24,55 +24,57 @@ #include "mu-container.hh" static gboolean -container_has_children (const MuContainer *c) +container_has_children(const MuContainer* c) { return c && c->child; } static gboolean -container_is_sibling_of (const MuContainer *c, const MuContainer *sibling) +container_is_sibling_of(const MuContainer* c, const MuContainer* sibling) { - const MuContainer *cur; + const MuContainer* cur; for (cur = c; cur; cur = cur->next) { if (cur == sibling) return TRUE; } - return container_is_sibling_of (sibling, c); + return container_is_sibling_of(sibling, c); } static void -test_mu_container_splice_children_when_parent_has_no_siblings (void) +test_mu_container_splice_children_when_parent_has_no_siblings(void) { MuContainer *child, *parent, *root_set; - child = mu_container_new (NULL, 0, "child"); - parent = mu_container_new (NULL, 0, "parent"); - parent = mu_container_append_children (parent, child); + child = mu_container_new(NULL, 0, "child"); + parent = mu_container_new(NULL, 0, "parent"); + parent = mu_container_append_children(parent, child); root_set = parent; - root_set = mu_container_splice_children (root_set, parent); + root_set = mu_container_splice_children(root_set, parent); - g_assert (root_set != NULL); - g_assert (!container_has_children(parent)); - g_assert (container_is_sibling_of (root_set, child)); + g_assert(root_set != NULL); + g_assert(!container_has_children(parent)); + g_assert(container_is_sibling_of(root_set, child)); mu_container_destroy(parent); mu_container_destroy(child); } int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/mu-container/mu-container-splice-children-when-parent-has-no-siblings", - test_mu_container_splice_children_when_parent_has_no_siblings); + g_test_add_func("/mu-container/mu-container-splice-children-when-parent-has-no-siblings", + test_mu_container_splice_children_when_parent_has_no_siblings); - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-mu-date.cc b/lib/test-mu-date.cc index 5cb6d5fa..ba87fbca 100644 --- a/lib/test-mu-date.cc +++ b/lib/test-mu-date.cc @@ -33,61 +33,46 @@ #include "test-mu-common.h" #include "mu-date.h" - - - - static void -test_mu_date_interpret_begin (void) +test_mu_date_interpret_begin(void) { time_t now; - now = time (NULL); + now = time(NULL); - g_assert_cmpstr (mu_date_interpret_s ("now", TRUE) , ==, - mu_date_str_s("%Y%m%d%H%M%S", now)); + g_assert_cmpstr(mu_date_interpret_s("now", TRUE), ==, mu_date_str_s("%Y%m%d%H%M%S", now)); - g_assert_cmpstr (mu_date_interpret_s ("today", TRUE) , ==, - mu_date_str_s("%Y%m%d000000", now)); + g_assert_cmpstr(mu_date_interpret_s("today", TRUE), ==, mu_date_str_s("%Y%m%d000000", now)); } static void -test_mu_date_interpret_end (void) +test_mu_date_interpret_end(void) { time_t now; - now = time (NULL); + now = time(NULL); - g_assert_cmpstr (mu_date_interpret_s ("now", FALSE) , ==, - mu_date_str_s("%Y%m%d%H%M%S", now)); + g_assert_cmpstr(mu_date_interpret_s("now", FALSE), ==, mu_date_str_s("%Y%m%d%H%M%S", now)); - g_assert_cmpstr (mu_date_interpret_s ("today", FALSE) , ==, - mu_date_str_s("%Y%m%d235959", now)); + g_assert_cmpstr(mu_date_interpret_s("today", FALSE), + ==, + mu_date_str_s("%Y%m%d235959", now)); } - - - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/mu-str/mu_date_parse_hdwmy", - test_mu_date_parse_hdwmy); - g_test_add_func ("/mu-str/mu_date_complete_begin", - test_mu_date_complete_begin); - g_test_add_func ("/mu-str/mu_date_complete_end", - test_mu_date_complete_end); + g_test_add_func("/mu-str/mu_date_parse_hdwmy", test_mu_date_parse_hdwmy); + g_test_add_func("/mu-str/mu_date_complete_begin", test_mu_date_complete_begin); + g_test_add_func("/mu-str/mu_date_complete_end", test_mu_date_complete_end); - g_test_add_func ("/mu-str/mu_date_interpret_begin", - test_mu_date_interpret_begin); - g_test_add_func ("/mu-str/mu_date_interpret_end", - test_mu_date_interpret_end); + g_test_add_func("/mu-str/mu_date_interpret_begin", test_mu_date_interpret_begin); + g_test_add_func("/mu-str/mu_date_interpret_end", test_mu_date_interpret_end); + g_log_set_handler(NULL, + G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, + (GLogFunc)black_hole, + NULL); - g_log_set_handler (NULL, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, - (GLogFunc)black_hole, NULL); - - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-mu-flags.cc b/lib/test-mu-flags.cc index 9c9c5754..df1e0bed 100644 --- a/lib/test-mu-flags.cc +++ b/lib/test-mu-flags.cc @@ -28,167 +28,166 @@ using namespace Mu; static void -test_mu_flag_char (void) +test_mu_flag_char(void) { - g_assert_cmpuint (mu_flag_char (MU_FLAG_DRAFT), ==, 'D'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_FLAGGED), ==, 'F'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_PASSED), ==, 'P'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_REPLIED), ==, 'R'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_SEEN), ==, 'S'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_TRASHED), ==, 'T'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_NEW), ==, 'N'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_SIGNED), ==, 'z'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_ENCRYPTED), ==, 'x'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_HAS_ATTACH), ==, 'a'); - g_assert_cmpuint (mu_flag_char (MU_FLAG_UNREAD), ==, 'u'); - g_assert_cmpuint (mu_flag_char ((MuFlags)12345), ==, 0); -} - - - -static void -test_mu_flag_name (void) -{ - g_assert_cmpstr (mu_flag_name (MU_FLAG_DRAFT), ==, "draft"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_FLAGGED), ==, "flagged"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_PASSED), ==, "passed"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_REPLIED), ==, "replied"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_SEEN), ==, "seen"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_TRASHED), ==, "trashed"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_NEW), ==, "new"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_SIGNED), ==, "signed"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_ENCRYPTED), ==, "encrypted"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_HAS_ATTACH), ==, "attach"); - g_assert_cmpstr (mu_flag_name (MU_FLAG_UNREAD), ==, "unread"); - g_assert_cmpstr (mu_flag_name ((MuFlags)12345), ==, NULL); + g_assert_cmpuint(mu_flag_char(MU_FLAG_DRAFT), ==, 'D'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_FLAGGED), ==, 'F'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_PASSED), ==, 'P'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_REPLIED), ==, 'R'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_SEEN), ==, 'S'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_TRASHED), ==, 'T'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_NEW), ==, 'N'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_SIGNED), ==, 'z'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_ENCRYPTED), ==, 'x'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_HAS_ATTACH), ==, 'a'); + g_assert_cmpuint(mu_flag_char(MU_FLAG_UNREAD), ==, 'u'); + g_assert_cmpuint(mu_flag_char((MuFlags)12345), ==, 0); } static void -test_mu_flags_to_str_s (void) +test_mu_flag_name(void) { - g_assert_cmpstr (mu_flags_to_str_s((MuFlags)(MU_FLAG_PASSED|MU_FLAG_SIGNED), - MU_FLAG_TYPE_ANY), - ==, "Pz"); - g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_ANY), - ==, "N"); - g_assert_cmpstr (mu_flags_to_str_s((MuFlags)(MU_FLAG_HAS_ATTACH|MU_FLAG_TRASHED), - MU_FLAG_TYPE_ANY), - ==, "Ta"); - g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_ANY), - ==, ""); - - g_assert_cmpstr (mu_flags_to_str_s((MuFlags)(MU_FLAG_PASSED|MU_FLAG_SIGNED), - MU_FLAG_TYPE_CONTENT), - ==, "z"); - - g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_MAILDIR), - ==, "N"); - g_assert_cmpstr (mu_flags_to_str_s((MuFlags)(MU_FLAG_HAS_ATTACH|MU_FLAG_TRASHED), - MU_FLAG_TYPE_MAILFILE), - ==, "T"); - - g_assert_cmpstr (mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_PSEUDO), - ==, ""); + g_assert_cmpstr(mu_flag_name(MU_FLAG_DRAFT), ==, "draft"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_FLAGGED), ==, "flagged"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_PASSED), ==, "passed"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_REPLIED), ==, "replied"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_SEEN), ==, "seen"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_TRASHED), ==, "trashed"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_NEW), ==, "new"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_SIGNED), ==, "signed"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_ENCRYPTED), ==, "encrypted"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_HAS_ATTACH), ==, "attach"); + g_assert_cmpstr(mu_flag_name(MU_FLAG_UNREAD), ==, "unread"); + g_assert_cmpstr(mu_flag_name((MuFlags)12345), ==, NULL); } +static void +test_mu_flags_to_str_s(void) +{ + g_assert_cmpstr( + mu_flags_to_str_s((MuFlags)(MU_FLAG_PASSED | MU_FLAG_SIGNED), MU_FLAG_TYPE_ANY), + ==, + "Pz"); + g_assert_cmpstr(mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_ANY), ==, "N"); + g_assert_cmpstr( + mu_flags_to_str_s((MuFlags)(MU_FLAG_HAS_ATTACH | MU_FLAG_TRASHED), MU_FLAG_TYPE_ANY), + ==, + "Ta"); + g_assert_cmpstr(mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_ANY), ==, ""); + + g_assert_cmpstr( + mu_flags_to_str_s((MuFlags)(MU_FLAG_PASSED | MU_FLAG_SIGNED), MU_FLAG_TYPE_CONTENT), + ==, + "z"); + + g_assert_cmpstr(mu_flags_to_str_s(MU_FLAG_NEW, MU_FLAG_TYPE_MAILDIR), ==, "N"); + g_assert_cmpstr(mu_flags_to_str_s((MuFlags)(MU_FLAG_HAS_ATTACH | MU_FLAG_TRASHED), + MU_FLAG_TYPE_MAILFILE), + ==, + "T"); + + g_assert_cmpstr(mu_flags_to_str_s(MU_FLAG_NONE, MU_FLAG_TYPE_PSEUDO), ==, ""); +} static void -test_mu_flags_from_str (void) +test_mu_flags_from_str(void) { /* note, the 3rd arg to mu_flags_from_str determines whether * invalid flags will be ignored (if TRUE) or MU_FLAG_INVALID (if FALSE) */ - g_assert_cmpuint (mu_flags_from_str ("RP", MU_FLAG_TYPE_ANY, TRUE), ==, - (MuFlags)( MU_FLAG_REPLIED | MU_FLAG_PASSED)); - g_assert_cmpuint (mu_flags_from_str ("Nz", MU_FLAG_TYPE_ANY, TRUE), ==, - MU_FLAG_NEW | MU_FLAG_SIGNED); - g_assert_cmpuint (mu_flags_from_str ("axD", MU_FLAG_TYPE_ANY, TRUE), ==, - (MuFlags)( MU_FLAG_HAS_ATTACH | MU_FLAG_ENCRYPTED | MU_FLAG_DRAFT)); + g_assert_cmpuint(mu_flags_from_str("RP", MU_FLAG_TYPE_ANY, TRUE), + ==, + (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_PASSED)); + g_assert_cmpuint(mu_flags_from_str("Nz", MU_FLAG_TYPE_ANY, TRUE), + ==, + MU_FLAG_NEW | MU_FLAG_SIGNED); + g_assert_cmpuint(mu_flags_from_str("axD", MU_FLAG_TYPE_ANY, TRUE), + ==, + (MuFlags)(MU_FLAG_HAS_ATTACH | MU_FLAG_ENCRYPTED | MU_FLAG_DRAFT)); - g_assert_cmpuint (mu_flags_from_str ("RP", MU_FLAG_TYPE_MAILFILE, TRUE), ==, - MU_FLAG_REPLIED | MU_FLAG_PASSED); - g_assert_cmpuint (mu_flags_from_str ("Nz", MU_FLAG_TYPE_MAILFILE, TRUE), ==, - MU_FLAG_NONE); + g_assert_cmpuint(mu_flags_from_str("RP", MU_FLAG_TYPE_MAILFILE, TRUE), + ==, + MU_FLAG_REPLIED | MU_FLAG_PASSED); + g_assert_cmpuint(mu_flags_from_str("Nz", MU_FLAG_TYPE_MAILFILE, TRUE), ==, MU_FLAG_NONE); /* ignore errors or not */ - g_assert_cmpuint (mu_flags_from_str ("qwi", MU_FLAG_TYPE_MAILFILE, FALSE), ==, - MU_FLAG_INVALID); - g_assert_cmpuint (mu_flags_from_str ("qwi", MU_FLAG_TYPE_MAILFILE, TRUE), ==, - 0); - - + g_assert_cmpuint(mu_flags_from_str("qwi", MU_FLAG_TYPE_MAILFILE, FALSE), + ==, + MU_FLAG_INVALID); + g_assert_cmpuint(mu_flags_from_str("qwi", MU_FLAG_TYPE_MAILFILE, TRUE), ==, 0); } static void -test_mu_flags_from_str_delta (void) +test_mu_flags_from_str_delta(void) { - g_assert_cmpuint (mu_flags_from_str_delta ("+S-R", - (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT), - MU_FLAG_TYPE_ANY),==, - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_DRAFT)); + g_assert_cmpuint(mu_flags_from_str_delta("+S-R", + (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT), + MU_FLAG_TYPE_ANY), + ==, + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_DRAFT)); - g_assert_cmpuint (mu_flags_from_str_delta ("", - (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT), - MU_FLAG_TYPE_ANY),==, - (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT)); + g_assert_cmpuint(mu_flags_from_str_delta("", + (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT), + MU_FLAG_TYPE_ANY), + ==, + (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_DRAFT)); - g_assert_cmpuint (mu_flags_from_str_delta ("-N+P+S-D", - (MuFlags)(MU_FLAG_SIGNED | MU_FLAG_DRAFT), - MU_FLAG_TYPE_ANY),==, - (MuFlags)(MU_FLAG_PASSED | MU_FLAG_SEEN | MU_FLAG_SIGNED)); + g_assert_cmpuint(mu_flags_from_str_delta("-N+P+S-D", + (MuFlags)(MU_FLAG_SIGNED | MU_FLAG_DRAFT), + MU_FLAG_TYPE_ANY), + ==, + (MuFlags)(MU_FLAG_PASSED | MU_FLAG_SEEN | MU_FLAG_SIGNED)); } - static void -test_mu_flags_custom_from_str (void) +test_mu_flags_custom_from_str(void) { unsigned u; struct { - const char *str; - const char *expected; - } cases[] = { - { "ABC", "ABC" }, - { "PAF", "A" }, - { "ShelloPwoFrDldR123", "helloworld123" }, - { "SPD", NULL } - }; + const char* str; + const char* expected; + } cases[] = {{"ABC", "ABC"}, + {"PAF", "A"}, + {"ShelloPwoFrDldR123", "helloworld123"}, + {"SPD", NULL}}; for (u = 0; u != G_N_ELEMENTS(cases); ++u) { - char *cust; - cust = mu_flags_custom_from_str (cases[u].str); + char* cust; + cust = mu_flags_custom_from_str(cases[u].str); if (g_test_verbose()) - g_print ("%s: str:%s; got:%s; expected:%s\n", - __func__, cases[u].str, cust, cases[u].expected); - g_assert_cmpstr (cust, ==, cases[u].expected); - g_free (cust); + g_print("%s: str:%s; got:%s; expected:%s\n", + __func__, + cases[u].str, + cust, + cases[u].expected); + g_assert_cmpstr(cust, ==, cases[u].expected); + g_free(cust); } } - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); /* mu_msg_str_date */ - g_test_add_func ("/mu-flags/test-mu-flag-char", test_mu_flag_char); - g_test_add_func ("/mu-flags/test-mu-flag-name",test_mu_flag_name); - g_test_add_func ("/mu-flags/test-mu-flags-to-str-s",test_mu_flags_to_str_s); - g_test_add_func ("/mu-flags/test-mu-flags-from-str",test_mu_flags_from_str); - g_test_add_func ("/mu-flags/test-mu-flags-from-str-delta",test_mu_flags_from_str_delta ); - g_test_add_func ("/mu-flags/test-mu-flags-custom-from-str", - test_mu_flags_custom_from_str); + g_test_add_func("/mu-flags/test-mu-flag-char", test_mu_flag_char); + g_test_add_func("/mu-flags/test-mu-flag-name", test_mu_flag_name); + g_test_add_func("/mu-flags/test-mu-flags-to-str-s", test_mu_flags_to_str_s); + g_test_add_func("/mu-flags/test-mu-flags-from-str", test_mu_flags_from_str); + g_test_add_func("/mu-flags/test-mu-flags-from-str-delta", test_mu_flags_from_str_delta); + g_test_add_func("/mu-flags/test-mu-flags-custom-from-str", test_mu_flags_custom_from_str); - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| - G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - rv = g_test_run (); + rv = g_test_run(); return rv; } diff --git a/lib/test-mu-maildir.cc b/lib/test-mu-maildir.cc index 5be3dddb..da1669f0 100644 --- a/lib/test-mu-maildir.cc +++ b/lib/test-mu-maildir.cc @@ -35,193 +35,158 @@ using namespace Mu; static void -test_mu_maildir_mkdir_01 (void) +test_mu_maildir_mkdir_01(void) { - int i; - gchar *tmpdir, *mdir, *tmp; - const gchar *subs[] = {"tmp", "cur", "new"}; + int i; + gchar * tmpdir, *mdir, *tmp; + const gchar* subs[] = {"tmp", "cur", "new"}; - tmpdir = test_mu_common_get_random_tmpdir (); - mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, - "cuux"); + tmpdir = test_mu_common_get_random_tmpdir(); + mdir = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "cuux"); - g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), - ==, TRUE); + g_assert_cmpuint(mu_maildir_mkdir(mdir, 0755, FALSE, NULL), ==, TRUE); for (i = 0; i != G_N_ELEMENTS(subs); ++i) { gchar* dir; - dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, - subs[i]); - g_assert_cmpuint (g_access (dir, R_OK), ==, 0); - g_assert_cmpuint (g_access (dir, W_OK), ==, 0); - g_free (dir); + dir = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, subs[i]); + g_assert_cmpuint(g_access(dir, R_OK), ==, 0); + g_assert_cmpuint(g_access(dir, W_OK), ==, 0); + g_free(dir); } - tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); - g_assert_cmpuint (g_access (tmp, F_OK), !=, 0); - - g_free (tmp); - g_free (tmpdir); - g_free (mdir); + tmp = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint(g_access(tmp, F_OK), !=, 0); + g_free(tmp); + g_free(tmpdir); + g_free(mdir); } - static void -test_mu_maildir_mkdir_02 (void) +test_mu_maildir_mkdir_02(void) { - int i; - gchar *tmpdir, *mdir, *tmp; - const gchar *subs[] = {"tmp", "cur", "new"}; + int i; + gchar * tmpdir, *mdir, *tmp; + const gchar* subs[] = {"tmp", "cur", "new"}; - tmpdir = test_mu_common_get_random_tmpdir (); - mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, - "cuux"); + tmpdir = test_mu_common_get_random_tmpdir(); + mdir = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "cuux"); - g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, TRUE, NULL), - ==, TRUE); + g_assert_cmpuint(mu_maildir_mkdir(mdir, 0755, TRUE, NULL), ==, TRUE); for (i = 0; i != G_N_ELEMENTS(subs); ++i) { gchar* dir; - dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, - subs[i]); - g_assert_cmpuint (g_access (dir, R_OK), ==, 0); + dir = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, subs[i]); + g_assert_cmpuint(g_access(dir, R_OK), ==, 0); - g_assert_cmpuint (g_access (dir, W_OK), ==, 0); - g_free (dir); + g_assert_cmpuint(g_access(dir, W_OK), ==, 0); + g_free(dir); } - tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); - g_assert_cmpuint (g_access (tmp, F_OK), ==, 0); + tmp = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint(g_access(tmp, F_OK), ==, 0); - g_free (tmp); - g_free (tmpdir); - g_free (mdir); + g_free(tmp); + g_free(tmpdir); + g_free(mdir); } - static void -test_mu_maildir_mkdir_03 (void) +test_mu_maildir_mkdir_03(void) { - int i; - gchar *tmpdir, *mdir, *tmp; - const gchar *subs[] = {"tmp", "cur", "new"}; + int i; + gchar * tmpdir, *mdir, *tmp; + const gchar* subs[] = {"tmp", "cur", "new"}; - tmpdir = test_mu_common_get_random_tmpdir (); - mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, - "cuux"); + tmpdir = test_mu_common_get_random_tmpdir(); + mdir = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "cuux"); /* create part of the structure already... */ { - gchar *dir; - dir = g_strdup_printf ("%s%ccur", mdir, G_DIR_SEPARATOR); - g_assert_cmpuint (g_mkdir_with_parents (dir, 0755), ==, 0); - g_free (dir); + gchar* dir; + dir = g_strdup_printf("%s%ccur", mdir, G_DIR_SEPARATOR); + g_assert_cmpuint(g_mkdir_with_parents(dir, 0755), ==, 0); + g_free(dir); } /* this should still work */ - g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), - ==, TRUE); + g_assert_cmpuint(mu_maildir_mkdir(mdir, 0755, FALSE, NULL), ==, TRUE); for (i = 0; i != G_N_ELEMENTS(subs); ++i) { gchar* dir; - dir = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, - subs[i]); - g_assert_cmpuint (g_access (dir, R_OK), ==, 0); - g_assert_cmpuint (g_access (dir, W_OK), ==, 0); - g_free (dir); + dir = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, subs[i]); + g_assert_cmpuint(g_access(dir, R_OK), ==, 0); + g_assert_cmpuint(g_access(dir, W_OK), ==, 0); + g_free(dir); } - tmp = g_strdup_printf ("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); - g_assert_cmpuint (g_access (tmp, F_OK), !=, 0); - - g_free (tmp); - g_free (tmpdir); - g_free (mdir); + tmp = g_strdup_printf("%s%c%s", mdir, G_DIR_SEPARATOR, ".noindex"); + g_assert_cmpuint(g_access(tmp, F_OK), !=, 0); + g_free(tmp); + g_free(tmpdir); + g_free(mdir); } - - static void -test_mu_maildir_mkdir_04 (void) +test_mu_maildir_mkdir_04(void) { gchar *tmpdir, *mdir; - tmpdir = test_mu_common_get_random_tmpdir (); - mdir = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, - "cuux"); + tmpdir = test_mu_common_get_random_tmpdir(); + mdir = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "cuux"); /* create part of the structure already... */ { - gchar *dir; - g_assert_cmpuint (g_mkdir_with_parents (mdir, 0755), ==, 0); - dir = g_strdup_printf ("%s%ccur", mdir, G_DIR_SEPARATOR); - g_assert_cmpuint (g_mkdir_with_parents (dir, 0000), ==, 0); - g_free (dir); + gchar* dir; + g_assert_cmpuint(g_mkdir_with_parents(mdir, 0755), ==, 0); + dir = g_strdup_printf("%s%ccur", mdir, G_DIR_SEPARATOR); + g_assert_cmpuint(g_mkdir_with_parents(dir, 0000), ==, 0); + g_free(dir); } /* this should fail now, because cur is not read/writable */ - g_assert_cmpuint (mu_maildir_mkdir (mdir, 0755, FALSE, NULL), - ==, (geteuid()==0 ? TRUE : FALSE)); - g_free (tmpdir); - g_free (mdir); + g_assert_cmpuint(mu_maildir_mkdir(mdir, 0755, FALSE, NULL), + ==, + (geteuid() == 0 ? TRUE : FALSE)); + g_free(tmpdir); + g_free(mdir); } - - - static gboolean -ignore_error (const char* log_domain, GLogLevelFlags log_level, const gchar* msg, - gpointer user_data) +ignore_error(const char* log_domain, GLogLevelFlags log_level, const gchar* msg, gpointer user_data) { return FALSE; /* don't abort */ } static void -test_mu_maildir_mkdir_05 (void) +test_mu_maildir_mkdir_05(void) { /* this must fail */ - g_test_log_set_fatal_handler ((GTestLogFatalFunc)ignore_error, NULL); + g_test_log_set_fatal_handler((GTestLogFatalFunc)ignore_error, NULL); - g_assert_cmpuint (mu_maildir_mkdir (NULL, 0755, TRUE, NULL), - ==, FALSE); + g_assert_cmpuint(mu_maildir_mkdir(NULL, 0755, TRUE, NULL), ==, FALSE); } static void -test_mu_maildir_get_flags_from_path (void) +test_mu_maildir_get_flags_from_path(void) { int i; struct { - const char *path; - MuFlags flags; - } paths[] = { - { - "/home/foo/Maildir/test/cur/123456:2,FSR", - (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_SEEN | MU_FLAG_FLAGGED) - }, - { - "/home/foo/Maildir/test/new/123456", - MU_FLAG_NEW - }, - { - /* NOTE: when in new/, the :2,.. stuff is ignored */ - "/home/foo/Maildir/test/new/123456:2,FR", - MU_FLAG_NEW - }, - { - "/home/foo/Maildir/test/cur/123456:2,DTP", - (MuFlags)(MU_FLAG_DRAFT | MU_FLAG_TRASHED | - MU_FLAG_PASSED) - }, - { - "/home/foo/Maildir/test/cur/123456:2,S", - MU_FLAG_SEEN - } - }; + const char* path; + MuFlags flags; + } paths[] = {{"/home/foo/Maildir/test/cur/123456:2,FSR", + (MuFlags)(MU_FLAG_REPLIED | MU_FLAG_SEEN | MU_FLAG_FLAGGED)}, + {"/home/foo/Maildir/test/new/123456", MU_FLAG_NEW}, + {/* NOTE: when in new/, the :2,.. stuff is ignored */ + "/home/foo/Maildir/test/new/123456:2,FR", + MU_FLAG_NEW}, + {"/home/foo/Maildir/test/cur/123456:2,DTP", + (MuFlags)(MU_FLAG_DRAFT | MU_FLAG_TRASHED | MU_FLAG_PASSED)}, + {"/home/foo/Maildir/test/cur/123456:2,S", MU_FLAG_SEEN}}; for (i = 0; i != G_N_ELEMENTS(paths); ++i) { MuFlags flags; @@ -230,257 +195,208 @@ test_mu_maildir_get_flags_from_path (void) } } - - static void -assert_matches_regexp (const char *str, const char *rx) +assert_matches_regexp(const char* str, const char* rx) { - if (!g_regex_match_simple (rx, str, (GRegexCompileFlags)0, - (GRegexMatchFlags)0)) { - if (g_test_verbose ()) - g_print ("%s does not match %s", str, rx); - g_assert (0); + if (!g_regex_match_simple(rx, str, (GRegexCompileFlags)0, (GRegexMatchFlags)0)) { + if (g_test_verbose()) + g_print("%s does not match %s", str, rx); + g_assert(0); } } - - static void -test_mu_maildir_get_new_path_new (void) +test_mu_maildir_get_new_path_new(void) { int i; struct { - const char *oldpath; - MuFlags flags; - const char *newpath; - } paths[] = { - { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_REPLIED, - "/home/foo/Maildir/test/cur/123456:2,R" - }, { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_NEW, - "/home/foo/Maildir/test/new/123456" - }, { - "/home/foo/Maildir/test/new/123456:2,FR", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), - "/home/foo/Maildir/test/cur/123456:2,RS" - }, { - "/home/foo/Maildir/test/new/1313038887_0.697:2,", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), - "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS" - }, { - "/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", - MU_FLAG_SEEN, - "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S" - } - }; + const char* oldpath; + MuFlags flags; + const char* newpath; + } paths[] = {{"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,R"}, + {"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, + "/home/foo/Maildir/test/new/123456"}, + {"/home/foo/Maildir/test/new/123456:2,FR", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), + "/home/foo/Maildir/test/cur/123456:2,RS"}, + {"/home/foo/Maildir/test/new/1313038887_0.697:2,", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), + "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS"}, + {"/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", + MU_FLAG_SEEN, + "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S"}}; for (i = 0; i != G_N_ELEMENTS(paths); ++i) { - char *str, *newbase; - str = mu_maildir_get_new_path (paths[i].oldpath, NULL, - paths[i].flags, TRUE); - newbase = g_path_get_basename (str); - assert_matches_regexp (newbase, - "\\d+\\." - "[[:xdigit:]]{16}\\." - "[[:alnum:]][[:alnum:]-]+(:2,.*)?"); - g_free (newbase); + char *str, *newbase; + str = mu_maildir_get_new_path(paths[i].oldpath, NULL, paths[i].flags, TRUE); + newbase = g_path_get_basename(str); + assert_matches_regexp(newbase, + "\\d+\\." + "[[:xdigit:]]{16}\\." + "[[:alnum:]][[:alnum:]-]+(:2,.*)?"); + g_free(newbase); g_free(str); } } - - - static void -test_mu_maildir_get_new_path_01 (void) +test_mu_maildir_get_new_path_01(void) { int i; struct { - const char *oldpath; - MuFlags flags; - const char *newpath; - } paths[] = { - { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_REPLIED, - "/home/foo/Maildir/test/cur/123456:2,R" - }, { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_NEW, - "/home/foo/Maildir/test/new/123456" - }, { - "/home/foo/Maildir/test/new/123456:2,FR", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), - "/home/foo/Maildir/test/cur/123456:2,RS" - }, { - "/home/foo/Maildir/test/new/1313038887_0.697:2,", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), - "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS" - }, { - "/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", - MU_FLAG_SEEN, - "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S" - } - }; + const char* oldpath; + MuFlags flags; + const char* newpath; + } paths[] = {{"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/test/cur/123456:2,R"}, + {"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, + "/home/foo/Maildir/test/new/123456"}, + {"/home/foo/Maildir/test/new/123456:2,FR", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), + "/home/foo/Maildir/test/cur/123456:2,RS"}, + {"/home/foo/Maildir/test/new/1313038887_0.697:2,", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), + "/home/foo/Maildir/test/cur/1313038887_0.697:2,FPS"}, + {"/home/djcb/Maildir/trash/new/1312920597.2206_16.cthulhu", + MU_FLAG_SEEN, + "/home/djcb/Maildir/trash/cur/1312920597.2206_16.cthulhu:2,S"}}; for (i = 0; i != G_N_ELEMENTS(paths); ++i) { - gchar *str; - str = mu_maildir_get_new_path(paths[i].oldpath, NULL, - paths[i].flags, FALSE); + gchar* str; + str = mu_maildir_get_new_path(paths[i].oldpath, NULL, paths[i].flags, FALSE); g_assert_cmpstr(str, ==, paths[i].newpath); g_free(str); } } - static void -test_mu_maildir_get_new_path_02 (void) +test_mu_maildir_get_new_path_02(void) { int i; struct { - const char *oldpath; - MuFlags flags; - const char *targetdir; - const char *newpath; - } paths[] = { - { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_REPLIED, "/home/foo/Maildir/blabla", - "/home/foo/Maildir/blabla/cur/123456:2,R" - }, { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_NEW, "/home/bar/Maildir/coffee", - "/home/bar/Maildir/coffee/new/123456" - }, { - "/home/foo/Maildir/test/new/123456", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), - "/home/cuux/Maildir/tea", - "/home/cuux/Maildir/tea/cur/123456:2,RS" - }, { - "/home/foo/Maildir/test/new/1313038887_0.697:2,", - (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), - "/home/boy/Maildir/stuff", - "/home/boy/Maildir/stuff/cur/1313038887_0.697:2,FPS" - } - }; + const char* oldpath; + MuFlags flags; + const char* targetdir; + const char* newpath; + } paths[] = {{"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,R"}, + {"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_NEW, + "/home/bar/Maildir/coffee", + "/home/bar/Maildir/coffee/new/123456"}, + {"/home/foo/Maildir/test/new/123456", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_REPLIED), + "/home/cuux/Maildir/tea", + "/home/cuux/Maildir/tea/cur/123456:2,RS"}, + {"/home/foo/Maildir/test/new/1313038887_0.697:2,", + (MuFlags)(MU_FLAG_SEEN | MU_FLAG_FLAGGED | MU_FLAG_PASSED), + "/home/boy/Maildir/stuff", + "/home/boy/Maildir/stuff/cur/1313038887_0.697:2,FPS"}}; for (i = 0; i != G_N_ELEMENTS(paths); ++i) { - gchar *str; + gchar* str; str = mu_maildir_get_new_path(paths[i].oldpath, - paths[i].targetdir, - paths[i].flags, FALSE); + paths[i].targetdir, + paths[i].flags, + FALSE); g_assert_cmpstr(str, ==, paths[i].newpath); g_free(str); } } - static void -test_mu_maildir_get_new_path_custom (void) +test_mu_maildir_get_new_path_custom(void) { int i; struct { - const char *oldpath; - MuFlags flags; - const char *targetdir; - const char *newpath; - } paths[] = { - { - "/home/foo/Maildir/test/cur/123456:2,FR", - MU_FLAG_REPLIED, "/home/foo/Maildir/blabla", - "/home/foo/Maildir/blabla/cur/123456:2,R" - }, { - "/home/foo/Maildir/test/cur/123456:2,hFeRllo123", - MU_FLAG_FLAGGED, "/home/foo/Maildir/blabla", - "/home/foo/Maildir/blabla/cur/123456:2,Fhello123" - }, { - "/home/foo/Maildir/test/cur/123456:2,abc", - MU_FLAG_PASSED, "/home/foo/Maildir/blabla", - "/home/foo/Maildir/blabla/cur/123456:2,Pabc" - } - }; + const char* oldpath; + MuFlags flags; + const char* targetdir; + const char* newpath; + } paths[] = {{"/home/foo/Maildir/test/cur/123456:2,FR", + MU_FLAG_REPLIED, + "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,R"}, + {"/home/foo/Maildir/test/cur/123456:2,hFeRllo123", + MU_FLAG_FLAGGED, + "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,Fhello123"}, + {"/home/foo/Maildir/test/cur/123456:2,abc", + MU_FLAG_PASSED, + "/home/foo/Maildir/blabla", + "/home/foo/Maildir/blabla/cur/123456:2,Pabc"}}; for (i = 0; i != G_N_ELEMENTS(paths); ++i) { - gchar *str; + gchar* str; str = mu_maildir_get_new_path(paths[i].oldpath, - paths[i].targetdir, - paths[i].flags, FALSE); + paths[i].targetdir, + paths[i].flags, + FALSE); g_assert_cmpstr(str, ==, paths[i].newpath); g_free(str); } } - - static void -test_mu_maildir_get_maildir_from_path (void) +test_mu_maildir_get_maildir_from_path(void) { unsigned u; struct { const char *path, *exp; - } cases[] = { - {"/home/foo/Maildir/test/cur/123456:2,FR", - "/home/foo/Maildir/test"}, - {"/home/foo/Maildir/lala/new/1313038887_0.697:2,", - "/home/foo/Maildir/lala"} - }; - + } cases[] = {{"/home/foo/Maildir/test/cur/123456:2,FR", "/home/foo/Maildir/test"}, + {"/home/foo/Maildir/lala/new/1313038887_0.697:2,", "/home/foo/Maildir/lala"}}; for (u = 0; u != G_N_ELEMENTS(cases); ++u) { - gchar *mdir; - mdir = mu_maildir_get_maildir_from_path (cases[u].path); - g_assert_cmpstr(mdir,==,cases[u].exp); - g_free (mdir); + gchar* mdir; + mdir = mu_maildir_get_maildir_from_path(cases[u].path); + g_assert_cmpstr(mdir, ==, cases[u].exp); + g_free(mdir); } } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); /* mu_util_maildir_mkmdir */ - g_test_add_func ("/mu-maildir/mu-maildir-mkdir-01", - test_mu_maildir_mkdir_01); - g_test_add_func ("/mu-maildir/mu-maildir-mkdir-02", - test_mu_maildir_mkdir_02); - g_test_add_func ("/mu-maildir/mu-maildir-mkdir-03", - test_mu_maildir_mkdir_03); - g_test_add_func ("/mu-maildir/mu-maildir-mkdir-04", - test_mu_maildir_mkdir_04); - g_test_add_func ("/mu-maildir/mu-maildir-mkdir-05", - test_mu_maildir_mkdir_05); + g_test_add_func("/mu-maildir/mu-maildir-mkdir-01", test_mu_maildir_mkdir_01); + g_test_add_func("/mu-maildir/mu-maildir-mkdir-02", test_mu_maildir_mkdir_02); + g_test_add_func("/mu-maildir/mu-maildir-mkdir-03", test_mu_maildir_mkdir_03); + g_test_add_func("/mu-maildir/mu-maildir-mkdir-04", test_mu_maildir_mkdir_04); + g_test_add_func("/mu-maildir/mu-maildir-mkdir-05", test_mu_maildir_mkdir_05); /* get/set flags */ g_test_add_func("/mu-maildir/mu-maildir-get-new-path-new", - test_mu_maildir_get_new_path_new); + test_mu_maildir_get_new_path_new); - g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01", - test_mu_maildir_get_new_path_01); - g_test_add_func("/mu-maildir/mu-maildir-get-new-path-02", - test_mu_maildir_get_new_path_02); + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01", test_mu_maildir_get_new_path_01); + g_test_add_func("/mu-maildir/mu-maildir-get-new-path-02", test_mu_maildir_get_new_path_02); g_test_add_func("/mu-maildir/mu-maildir-get-new-path-custom", - test_mu_maildir_get_new_path_custom); + test_mu_maildir_get_new_path_custom); g_test_add_func("/mu-maildir/mu-maildir-get-flags-from-path", - test_mu_maildir_get_flags_from_path); - + test_mu_maildir_get_flags_from_path); g_test_add_func("/mu-maildir/mu-maildir-get-maildir-from-path", - test_mu_maildir_get_maildir_from_path); + test_mu_maildir_get_maildir_from_path); - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| - G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-mu-msg-fields.cc b/lib/test-mu-msg-fields.cc index 15cbcda2..bf3db22c 100644 --- a/lib/test-mu-msg-fields.cc +++ b/lib/test-mu-msg-fields.cc @@ -32,103 +32,95 @@ #include "mu-msg-fields.h" static void -test_mu_msg_field_body (void) +test_mu_msg_field_body(void) { MuMsgFieldId field; field = MU_MSG_FIELD_ID_BODY_TEXT; - g_assert_cmpstr (mu_msg_field_name(field),==, "body"); - g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'b'); - g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'B'); + g_assert_cmpstr(mu_msg_field_name(field), ==, "body"); + g_assert_cmpuint(mu_msg_field_shortcut(field), ==, 'b'); + g_assert_cmpuint(mu_msg_field_xapian_prefix(field), ==, 'B'); - g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, FALSE); + g_assert_cmpuint(mu_msg_field_is_numeric(field), ==, FALSE); } static void -test_mu_msg_field_subject (void) +test_mu_msg_field_subject(void) { MuMsgFieldId field; field = MU_MSG_FIELD_ID_SUBJECT; - g_assert_cmpstr (mu_msg_field_name(field),==, "subject"); - g_assert_cmpuint (mu_msg_field_shortcut(field),==, 's'); - g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'S'); + g_assert_cmpstr(mu_msg_field_name(field), ==, "subject"); + g_assert_cmpuint(mu_msg_field_shortcut(field), ==, 's'); + g_assert_cmpuint(mu_msg_field_xapian_prefix(field), ==, 'S'); - g_assert_cmpuint (mu_msg_field_is_numeric(field), ==,FALSE); + g_assert_cmpuint(mu_msg_field_is_numeric(field), ==, FALSE); } static void -test_mu_msg_field_to (void) +test_mu_msg_field_to(void) { MuMsgFieldId field; field = MU_MSG_FIELD_ID_TO; - g_assert_cmpstr (mu_msg_field_name(field),==, "to"); - g_assert_cmpuint (mu_msg_field_shortcut(field),==, 't'); - g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'T'); + g_assert_cmpstr(mu_msg_field_name(field), ==, "to"); + g_assert_cmpuint(mu_msg_field_shortcut(field), ==, 't'); + g_assert_cmpuint(mu_msg_field_xapian_prefix(field), ==, 'T'); - g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, FALSE); + g_assert_cmpuint(mu_msg_field_is_numeric(field), ==, FALSE); } - static void -test_mu_msg_field_prio (void) +test_mu_msg_field_prio(void) { MuMsgFieldId field; field = MU_MSG_FIELD_ID_PRIO; - g_assert_cmpstr (mu_msg_field_name(field),==, "prio"); - g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'p'); - g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'P'); + g_assert_cmpstr(mu_msg_field_name(field), ==, "prio"); + g_assert_cmpuint(mu_msg_field_shortcut(field), ==, 'p'); + g_assert_cmpuint(mu_msg_field_xapian_prefix(field), ==, 'P'); - g_assert_cmpuint (mu_msg_field_is_numeric(field), ==, TRUE); + g_assert_cmpuint(mu_msg_field_is_numeric(field), ==, TRUE); } static void -test_mu_msg_field_flags (void) +test_mu_msg_field_flags(void) { MuMsgFieldId field; field = MU_MSG_FIELD_ID_FLAGS; - g_assert_cmpstr (mu_msg_field_name(field),==, "flag"); - g_assert_cmpuint (mu_msg_field_shortcut(field),==, 'g'); - g_assert_cmpuint (mu_msg_field_xapian_prefix(field),==, 'G'); + g_assert_cmpstr(mu_msg_field_name(field), ==, "flag"); + g_assert_cmpuint(mu_msg_field_shortcut(field), ==, 'g'); + g_assert_cmpuint(mu_msg_field_xapian_prefix(field), ==, 'G'); - g_assert_cmpuint (mu_msg_field_is_numeric(field),==, TRUE); + g_assert_cmpuint(mu_msg_field_is_numeric(field), ==, TRUE); } - - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); /* mu_msg_str_date */ - g_test_add_func ("/mu-msg-fields/mu-msg-field-body", - test_mu_msg_field_body); - g_test_add_func ("/mu-msg-fields/mu-msg-field-subject", - test_mu_msg_field_subject); - g_test_add_func ("/mu-msg-fields/mu-msg-field-to", - test_mu_msg_field_to); - g_test_add_func ("/mu-msg-fields/mu-msg-field-prio", - test_mu_msg_field_prio); - g_test_add_func ("/mu-msg-fields/mu-msg-field-flags", - test_mu_msg_field_flags); + g_test_add_func("/mu-msg-fields/mu-msg-field-body", test_mu_msg_field_body); + g_test_add_func("/mu-msg-fields/mu-msg-field-subject", test_mu_msg_field_subject); + g_test_add_func("/mu-msg-fields/mu-msg-field-to", test_mu_msg_field_to); + g_test_add_func("/mu-msg-fields/mu-msg-field-prio", test_mu_msg_field_prio); + g_test_add_func("/mu-msg-fields/mu-msg-field-flags", test_mu_msg_field_flags); /* FIXME: add tests for mu_msg_str_flags; but note the * function simply calls mu_msg_field_str */ - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | - G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-mu-msg.cc b/lib/test-mu-msg.cc index 7513ef27..75110dac 100644 --- a/lib/test-mu-msg.cc +++ b/lib/test-mu-msg.cc @@ -34,566 +34,471 @@ using namespace Mu; - static MuMsg* -get_msg (const char *path) +get_msg(const char* path) { - GError *err; - MuMsg *msg; + GError* err; + MuMsg* msg; - if (g_test_verbose ()) - g_print (">> %s\n", path); + if (g_test_verbose()) + g_print(">> %s\n", path); err = NULL; - msg = mu_msg_new_from_file (path, NULL, &err); + msg = mu_msg_new_from_file(path, NULL, &err); if (!msg) { - g_printerr ("failed to load %s: %s\n", - path, err ? err->message : "something went wrong"); - g_clear_error (&err); - g_assert (0); + g_printerr("failed to load %s: %s\n", + path, + err ? err->message : "something went wrong"); + g_clear_error(&err); + g_assert(0); } return msg; } - - static gboolean -check_contact_01 (MuMsgContact *contact, int *idx) +check_contact_01(MuMsgContact* contact, int* idx) { switch (*idx) { case 0: - g_assert_cmpstr (mu_msg_contact_name (contact), - ==, "Mickey Mouse"); - g_assert_cmpstr (mu_msg_contact_email (contact), - ==, "anon@example.com"); + g_assert_cmpstr(mu_msg_contact_name(contact), ==, "Mickey Mouse"); + g_assert_cmpstr(mu_msg_contact_email(contact), ==, "anon@example.com"); break; case 1: - g_assert_cmpstr (mu_msg_contact_name (contact), - ==, "Donald Duck"); - g_assert_cmpstr (mu_msg_contact_email (contact), - ==, "gcc-help@gcc.gnu.org"); + g_assert_cmpstr(mu_msg_contact_name(contact), ==, "Donald Duck"); + g_assert_cmpstr(mu_msg_contact_email(contact), ==, "gcc-help@gcc.gnu.org"); break; - default: - g_assert_not_reached (); + default: g_assert_not_reached(); } ++(*idx); return TRUE; } - static void -test_mu_msg_01 (void) +test_mu_msg_01(void) { - MuMsg *msg; - gint i; + MuMsg* msg; + gint i; - msg = get_msg (MU_TESTMAILDIR4 "/1220863042.12663_1.mindcrime!2,S"); + msg = get_msg(MU_TESTMAILDIR4 "/1220863042.12663_1.mindcrime!2,S"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "Donald Duck "); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "gcc include search order"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "Mickey Mouse "); - g_assert_cmpstr (mu_msg_get_msgid(msg), - ==, "3BE9E6535E3029448670913581E7A1A20D852173@" - "emss35m06.us.lmco.com"); - g_assert_cmpstr (mu_msg_get_header(msg, "Mailing-List"), - ==, - "contact gcc-help-help@gcc.gnu.org; run by ezmlm"); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'klub' */ - ==, MU_MSG_PRIO_NORMAL); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 1217530645); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "Donald Duck "); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "gcc include search order"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "Mickey Mouse "); + g_assert_cmpstr(mu_msg_get_msgid(msg), + ==, + "3BE9E6535E3029448670913581E7A1A20D852173@" + "emss35m06.us.lmco.com"); + g_assert_cmpstr(mu_msg_get_header(msg, "Mailing-List"), + ==, + "contact gcc-help-help@gcc.gnu.org; run by ezmlm"); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'klub' */ + ==, + MU_MSG_PRIO_NORMAL); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 1217530645); i = 0; - mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)check_contact_01, - &i); - g_assert_cmpint (i,==,2); + mu_msg_contact_foreach(msg, (MuMsgContactForeachFunc)check_contact_01, &i); + g_assert_cmpint(i, ==, 2); - mu_msg_unref (msg); + mu_msg_unref(msg); } - - - - - static gboolean -check_contact_02 (MuMsgContact *contact, int *idx) +check_contact_02(MuMsgContact* contact, int* idx) { switch (*idx) { case 0: - g_assert_cmpstr (mu_msg_contact_name (contact), - ==, NULL); - g_assert_cmpstr (mu_msg_contact_email (contact), - ==, "anon@example.com"); + g_assert_cmpstr(mu_msg_contact_name(contact), ==, NULL); + g_assert_cmpstr(mu_msg_contact_email(contact), ==, "anon@example.com"); break; case 1: - g_assert_cmpstr (mu_msg_contact_name (contact), - ==, NULL); - g_assert_cmpstr (mu_msg_contact_email (contact), - ==, "help-gnu-emacs@gnu.org"); + g_assert_cmpstr(mu_msg_contact_name(contact), ==, NULL); + g_assert_cmpstr(mu_msg_contact_email(contact), ==, "help-gnu-emacs@gnu.org"); break; - default: - g_assert_not_reached (); + default: g_assert_not_reached(); } ++(*idx); return TRUE; } - - static void -test_mu_msg_02 (void) +test_mu_msg_02(void) { - MuMsg *msg; - int i; + MuMsg* msg; + int i; - msg = get_msg (MU_TESTMAILDIR4 "/1220863087.12663_19.mindcrime!2,S"); + msg = get_msg(MU_TESTMAILDIR4 "/1220863087.12663_19.mindcrime!2,S"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "help-gnu-emacs@gnu.org"); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "Re: Learning LISP; Scheme vs elisp."); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "anon@example.com"); - g_assert_cmpstr (mu_msg_get_msgid(msg), - ==, "r6bpm5-6n6.ln1@news.ducksburg.com"); - g_assert_cmpstr (mu_msg_get_header(msg, "Errors-To"), - ==, "help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org"); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_LOW); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 1218051515); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "help-gnu-emacs@gnu.org"); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "Re: Learning LISP; Scheme vs elisp."); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "anon@example.com"); + g_assert_cmpstr(mu_msg_get_msgid(msg), ==, "r6bpm5-6n6.ln1@news.ducksburg.com"); + g_assert_cmpstr(mu_msg_get_header(msg, "Errors-To"), + ==, + "help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org"); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_LOW); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 1218051515); i = 0; - mu_msg_contact_foreach (msg, - (MuMsgContactForeachFunc)check_contact_02, - &i); - g_assert_cmpint (i,==,2); - g_assert_cmpuint (mu_msg_get_flags(msg), ==, MU_FLAG_SEEN|MU_FLAG_LIST); + mu_msg_contact_foreach(msg, (MuMsgContactForeachFunc)check_contact_02, &i); + g_assert_cmpint(i, ==, 2); + g_assert_cmpuint(mu_msg_get_flags(msg), ==, MU_FLAG_SEEN | MU_FLAG_LIST); - mu_msg_unref (msg); + mu_msg_unref(msg); } static void -test_mu_msg_03 (void) +test_mu_msg_03(void) { - MuMsg *msg; - const GSList *params; + MuMsg* msg; + const GSList* params; - msg = get_msg (MU_TESTMAILDIR4 "/1283599333.1840_11.cthulhu!2,"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "Bilbo Baggins "); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "Greetings from Lothlórien"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "Frodo Baggins "); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_NORMAL); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 0); - g_assert_cmpstr (mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), - ==, - "\nLet's write some fünkÿ text\nusing umlauts.\n\nFoo.\n"); + msg = get_msg(MU_TESTMAILDIR4 "/1283599333.1840_11.cthulhu!2,"); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "Bilbo Baggins "); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "Greetings from Lothlórien"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "Frodo Baggins "); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_NORMAL); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 0); + g_assert_cmpstr(mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), + ==, + "\nLet's write some fünkÿ text\nusing umlauts.\n\nFoo.\n"); - params = mu_msg_get_body_text_content_type_parameters( - msg, MU_MSG_OPTION_NONE); - g_assert_cmpuint (g_slist_length ((GSList*)params), ==, 2); + params = mu_msg_get_body_text_content_type_parameters(msg, MU_MSG_OPTION_NONE); + g_assert_cmpuint(g_slist_length((GSList*)params), ==, 2); - g_assert_cmpstr ((char*)params->data,==, "charset"); + g_assert_cmpstr((char*)params->data, ==, "charset"); params = g_slist_next(params); - g_assert_cmpstr ((char*)params->data,==,"UTF-8"); + g_assert_cmpstr((char*)params->data, ==, "UTF-8"); - g_assert_cmpuint (mu_msg_get_flags(msg), - ==, MU_FLAG_UNREAD); /* not seen => unread */ + g_assert_cmpuint(mu_msg_get_flags(msg), ==, MU_FLAG_UNREAD); /* not seen => unread */ - mu_msg_unref (msg); + mu_msg_unref(msg); } - static void -test_mu_msg_04 (void) +test_mu_msg_04(void) { - MuMsg *msg; + MuMsg* msg; - msg = get_msg (MU_TESTMAILDIR4 "/mail5"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "George Custer "); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "pics for you"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "Sitting Bull "); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_NORMAL); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 0); - g_assert_cmpuint (mu_msg_get_flags(msg), - ==, MU_FLAG_HAS_ATTACH|MU_FLAG_UNREAD); - mu_msg_unref (msg); + msg = get_msg(MU_TESTMAILDIR4 "/mail5"); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "George Custer "); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "pics for you"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "Sitting Bull "); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_NORMAL); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 0); + g_assert_cmpuint(mu_msg_get_flags(msg), ==, MU_FLAG_HAS_ATTACH | MU_FLAG_UNREAD); + mu_msg_unref(msg); } - static void -test_mu_msg_multimime (void) +test_mu_msg_multimime(void) { - MuMsg *msg; + MuMsg* msg; - msg = get_msg (MU_TESTMAILDIR4 "/multimime!2,FS"); + msg = get_msg(MU_TESTMAILDIR4 "/multimime!2,FS"); /* ie., are text parts properly concatenated? */ - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "multimime"); - g_assert_cmpstr (mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), - ==, "abcdef"); - g_assert_cmpuint (mu_msg_get_flags(msg), - ==, (MuFlags)(MU_FLAG_FLAGGED | MU_FLAG_SEEN | - MU_FLAG_HAS_ATTACH)); - mu_msg_unref (msg); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "multimime"); + g_assert_cmpstr(mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), ==, "abcdef"); + g_assert_cmpuint(mu_msg_get_flags(msg), + ==, + (MuFlags)(MU_FLAG_FLAGGED | MU_FLAG_SEEN | MU_FLAG_HAS_ATTACH)); + mu_msg_unref(msg); } - - static void -test_mu_msg_flags (void) +test_mu_msg_flags(void) { unsigned u; struct { - const char *path; - MuFlags flags; - } msgflags [] = { - { MU_TESTMAILDIR4 "/multimime!2,FS", - (MuFlags)(MU_FLAG_FLAGGED | MU_FLAG_SEEN | - MU_FLAG_HAS_ATTACH) }, - { MU_TESTMAILDIR4 "/special!2,Sabc", - MU_FLAG_SEEN } + const char* path; + MuFlags flags; + } msgflags[] = {{MU_TESTMAILDIR4 "/multimime!2,FS", + (MuFlags)(MU_FLAG_FLAGGED | MU_FLAG_SEEN | MU_FLAG_HAS_ATTACH)}, + {MU_TESTMAILDIR4 "/special!2,Sabc", MU_FLAG_SEEN} }; for (u = 0; u != G_N_ELEMENTS(msgflags); ++u) { - MuMsg *msg; + MuMsg* msg; MuFlags flags; - g_assert ((msg = get_msg (msgflags[u].path))); - flags = mu_msg_get_flags (msg); + g_assert((msg = get_msg(msgflags[u].path))); + flags = mu_msg_get_flags(msg); if (g_test_verbose()) - g_print ("=> %s [ %s, %u] <=> [ %s, %u]\n", - msgflags[u].path, - mu_flags_to_str_s(msgflags[u].flags, - MU_FLAG_TYPE_ANY), - (unsigned)msgflags[u].flags, - mu_flags_to_str_s(flags, MU_FLAG_TYPE_ANY), - (unsigned)flags); - g_assert_cmpuint (flags ,==, msgflags[u].flags); - mu_msg_unref (msg); + g_print("=> %s [ %s, %u] <=> [ %s, %u]\n", + msgflags[u].path, + mu_flags_to_str_s(msgflags[u].flags, MU_FLAG_TYPE_ANY), + (unsigned)msgflags[u].flags, + mu_flags_to_str_s(flags, MU_FLAG_TYPE_ANY), + (unsigned)flags); + g_assert_cmpuint(flags, ==, msgflags[u].flags); + mu_msg_unref(msg); } } - static void -test_mu_msg_umlaut (void) +test_mu_msg_umlaut(void) { - MuMsg *msg; + MuMsg* msg; - msg = get_msg (MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "Helmut Kröger "); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "Motörhead"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "Mü "); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_NORMAL); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 0); + msg = get_msg(MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "Helmut Kröger "); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "Motörhead"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "Mü "); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_NORMAL); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 0); - mu_msg_unref (msg); + mu_msg_unref(msg); } - static void -test_mu_msg_references (void) +test_mu_msg_references(void) { - MuMsg *msg; - const GSList *refs; + MuMsg* msg; + const GSList* refs; - msg = get_msg (MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); + msg = get_msg(MU_TESTMAILDIR4 "/1305664394.2171_402.cthulhu!2,"); refs = mu_msg_get_references(msg); - g_assert_cmpuint (g_slist_length ((GSList*)refs), ==, 4); + g_assert_cmpuint(g_slist_length((GSList*)refs), ==, 4); - g_assert_cmpstr ((char*)refs->data,==, "non-exist-01@msg.id"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, "non-exist-02@msg.id"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, "non-exist-03@msg.id"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, "non-exist-04@msg.id"); - refs = g_slist_next (refs); + g_assert_cmpstr((char*)refs->data, ==, "non-exist-01@msg.id"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "non-exist-02@msg.id"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "non-exist-03@msg.id"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "non-exist-04@msg.id"); + refs = g_slist_next(refs); - mu_msg_unref (msg); + mu_msg_unref(msg); } - - static void -test_mu_msg_references_dups (void) +test_mu_msg_references_dups(void) { - MuMsg *msg; - const GSList *refs; - const char *mlist; + MuMsg* msg; + const GSList* refs; + const char* mlist; - msg = get_msg (MU_TESTMAILDIR4 "/1252168370_3.14675.cthulhu!2,S"); + msg = get_msg(MU_TESTMAILDIR4 "/1252168370_3.14675.cthulhu!2,S"); refs = mu_msg_get_references(msg); /* make sure duplicate msg-ids are filtered out */ - g_assert_cmpuint (g_slist_length ((GSList*)refs), ==, 6); + g_assert_cmpuint(g_slist_length((GSList*)refs), ==, 6); - g_assert_cmpstr ((char*)refs->data,==, - "439C1136.90504@euler.org"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, - "4399DD94.5070309@euler.org"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, - "20051209233303.GA13812@gauss.org"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, - "439B41ED.2080402@euler.org"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, - "439A1E03.3090604@euler.org"); - refs = g_slist_next (refs); - g_assert_cmpstr ((char*)refs->data,==, - "20051211184308.GB13513@gauss.org"); - refs = g_slist_next (refs); + g_assert_cmpstr((char*)refs->data, ==, "439C1136.90504@euler.org"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "4399DD94.5070309@euler.org"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "20051209233303.GA13812@gauss.org"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "439B41ED.2080402@euler.org"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "439A1E03.3090604@euler.org"); + refs = g_slist_next(refs); + g_assert_cmpstr((char*)refs->data, ==, "20051211184308.GB13513@gauss.org"); + refs = g_slist_next(refs); - mlist = mu_msg_get_mailing_list (msg); - g_assert_cmpstr (mlist ,==, "Example of List Id"); + mlist = mu_msg_get_mailing_list(msg); + g_assert_cmpstr(mlist, ==, "Example of List Id"); - mu_msg_unref (msg); + mu_msg_unref(msg); } - static void -test_mu_msg_references_many (void) +test_mu_msg_references_many(void) { - MuMsg *msg; - unsigned u; + MuMsg* msg; + unsigned u; const GSList *refs, *cur; - const char* expt_refs[] = { - "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt.googlegroups.com", - "87hbblwelr.fsf@sapphire.mobileactivedefense.com", - "pql248-4va.ln1@wilbur.25thandClement.com", - "ikns6r$li3$1@Iltempo.Update.UU.SE", - "8762s0jreh.fsf@sapphire.mobileactivedefense.com", - "ikqqp1$jv0$1@Iltempo.Update.UU.SE", - "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com", - "ikr0na$lru$1@Iltempo.Update.UU.SE", - "tO8cp.1228$GE6.370@news.usenetserver.com", - "ikr6ks$nlf$1@Iltempo.Update.UU.SE", - "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk" - }; + const char* expt_refs[] = { + "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt.googlegroups.com", + "87hbblwelr.fsf@sapphire.mobileactivedefense.com", + "pql248-4va.ln1@wilbur.25thandClement.com", + "ikns6r$li3$1@Iltempo.Update.UU.SE", + "8762s0jreh.fsf@sapphire.mobileactivedefense.com", + "ikqqp1$jv0$1@Iltempo.Update.UU.SE", + "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com", + "ikr0na$lru$1@Iltempo.Update.UU.SE", + "tO8cp.1228$GE6.370@news.usenetserver.com", + "ikr6ks$nlf$1@Iltempo.Update.UU.SE", + "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk"}; - msg = get_msg (MU_TESTMAILDIR2 "/bar/cur/181736.eml"); + msg = get_msg(MU_TESTMAILDIR2 "/bar/cur/181736.eml"); refs = mu_msg_get_references(msg); - g_assert_cmpuint (G_N_ELEMENTS(expt_refs), ==, - g_slist_length((GSList*)refs)); + g_assert_cmpuint(G_N_ELEMENTS(expt_refs), ==, g_slist_length((GSList*)refs)); for (cur = refs, u = 0; cur; cur = g_slist_next(cur), ++u) { if (g_test_verbose()) - g_print ("%u. '%s' =? '%s'\n", - u, (char*)cur->data, - expt_refs[u]); + g_print("%u. '%s' =? '%s'\n", u, (char*)cur->data, expt_refs[u]); - g_assert_cmpstr ((char*)cur->data, ==, expt_refs[u]); + g_assert_cmpstr((char*)cur->data, ==, expt_refs[u]); } - mu_msg_unref (msg); + mu_msg_unref(msg); } static void -test_mu_msg_tags (void) +test_mu_msg_tags(void) { - MuMsg *msg; - const GSList *tags; + MuMsg* msg; + const GSList* tags; - msg = get_msg (MU_TESTMAILDIR4 "/mail1"); + msg = get_msg(MU_TESTMAILDIR4 "/mail1"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, "Julius Caesar "); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "Fere libenter homines id quod volunt credunt"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "John Milton "); - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_HIGH); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 1217530645); + g_assert_cmpstr(mu_msg_get_to(msg), ==, "Julius Caesar "); + g_assert_cmpstr(mu_msg_get_subject(msg), + ==, + "Fere libenter homines id quod volunt credunt"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "John Milton "); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_HIGH); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 1217530645); - tags = mu_msg_get_tags (msg); - g_assert_cmpstr ((char*)tags->data,==,"Paradise"); - g_assert_cmpstr ((char*)tags->next->data,==,"losT"); - g_assert_cmpstr ((char*)tags->next->next->data,==,"john"); - g_assert_cmpstr ((char*)tags->next->next->next->data,==,"milton"); + tags = mu_msg_get_tags(msg); + g_assert_cmpstr((char*)tags->data, ==, "Paradise"); + g_assert_cmpstr((char*)tags->next->data, ==, "losT"); + g_assert_cmpstr((char*)tags->next->next->data, ==, "john"); + g_assert_cmpstr((char*)tags->next->next->next->data, ==, "milton"); - g_assert (!tags->next->next->next->next); + g_assert(!tags->next->next->next->next); - mu_msg_unref (msg); + mu_msg_unref(msg); } - static void -test_mu_msg_comp_unix_programmer (void) +test_mu_msg_comp_unix_programmer(void) { - MuMsg *msg; - char *refs; + MuMsg* msg; + char* refs; - msg = get_msg (MU_TESTMAILDIR4 "/181736.eml"); - g_assert_cmpstr (mu_msg_get_to(msg), - ==, NULL); - g_assert_cmpstr (mu_msg_get_subject(msg), - ==, "Re: Are writes \"atomic\" to readers of the file?"); - g_assert_cmpstr (mu_msg_get_from(msg), - ==, "Jimbo Foobarcuux "); - g_assert_cmpstr (mu_msg_get_msgid(msg), - ==, "oktdp.42997$Te.22361@news.usenetserver.com"); + msg = get_msg(MU_TESTMAILDIR4 "/181736.eml"); + g_assert_cmpstr(mu_msg_get_to(msg), ==, NULL); + g_assert_cmpstr(mu_msg_get_subject(msg), + ==, + "Re: Are writes \"atomic\" to readers of the file?"); + g_assert_cmpstr(mu_msg_get_from(msg), ==, "Jimbo Foobarcuux "); + g_assert_cmpstr(mu_msg_get_msgid(msg), ==, "oktdp.42997$Te.22361@news.usenetserver.com"); - refs = mu_str_from_list (mu_msg_get_references(msg), ','); - g_assert_cmpstr (refs, ==, - "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt" - ".googlegroups.com," - "87hbblwelr.fsf@sapphire.mobileactivedefense.com," - "pql248-4va.ln1@wilbur.25thandClement.com," - "ikns6r$li3$1@Iltempo.Update.UU.SE," - "8762s0jreh.fsf@sapphire.mobileactivedefense.com," - "ikqqp1$jv0$1@Iltempo.Update.UU.SE," - "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com," - "ikr0na$lru$1@Iltempo.Update.UU.SE," - "tO8cp.1228$GE6.370@news.usenetserver.com," - "ikr6ks$nlf$1@Iltempo.Update.UU.SE," - "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk"); - g_free (refs); + refs = mu_str_from_list(mu_msg_get_references(msg), ','); + g_assert_cmpstr(refs, + ==, + "e9065dac-13c1-4103-9e31-6974ca232a89@t15g2000prt" + ".googlegroups.com," + "87hbblwelr.fsf@sapphire.mobileactivedefense.com," + "pql248-4va.ln1@wilbur.25thandClement.com," + "ikns6r$li3$1@Iltempo.Update.UU.SE," + "8762s0jreh.fsf@sapphire.mobileactivedefense.com," + "ikqqp1$jv0$1@Iltempo.Update.UU.SE," + "87hbbjc5jt.fsf@sapphire.mobileactivedefense.com," + "ikr0na$lru$1@Iltempo.Update.UU.SE," + "tO8cp.1228$GE6.370@news.usenetserver.com," + "ikr6ks$nlf$1@Iltempo.Update.UU.SE," + "8ioh48-8mu.ln1@leafnode-msgid.gclare.org.uk"); + g_free(refs); //"jimbo@slp53.sl.home (Jimbo Foobarcuux)"; - g_assert_cmpuint (mu_msg_get_prio(msg), /* 'low' */ - ==, MU_MSG_PRIO_NORMAL); - g_assert_cmpuint (mu_msg_get_date(msg), - ==, 1299603860); + g_assert_cmpuint(mu_msg_get_prio(msg), /* 'low' */ + ==, + MU_MSG_PRIO_NORMAL); + g_assert_cmpuint(mu_msg_get_date(msg), ==, 1299603860); - mu_msg_unref (msg); + mu_msg_unref(msg); } - - static void -test_mu_str_prio_01 (void) +test_mu_str_prio_01(void) { g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_LOW), ==, "low"); g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_NORMAL), ==, "normal"); g_assert_cmpstr(mu_msg_prio_name(MU_MSG_PRIO_HIGH), ==, "high"); } - static gboolean -ignore_error (const char* log_domain, GLogLevelFlags log_level, - const gchar* msg, gpointer user_data) +ignore_error(const char* log_domain, GLogLevelFlags log_level, const gchar* msg, gpointer user_data) { return FALSE; /* don't abort */ } - static void -test_mu_str_prio_02 (void) +test_mu_str_prio_02(void) { /* this must fail */ - g_test_log_set_fatal_handler ((GTestLogFatalFunc)ignore_error, NULL); - g_assert_cmpstr (mu_msg_prio_name((MuMsgPrio)666), ==, NULL); + g_test_log_set_fatal_handler((GTestLogFatalFunc)ignore_error, NULL); + g_assert_cmpstr(mu_msg_prio_name((MuMsgPrio)666), ==, NULL); } - - static void -test_mu_str_display_contact (void) +test_mu_str_display_contact(void) { - int i; + int i; struct { - const char* word; - const char* disp; - } words [] = { - { "\"Foo Bar\" ", "Foo Bar"}, - { "Foo Bar ", "Foo Bar" }, - { "", "aap@noot.mies" }, - { "foo@bar.nl", "foo@bar.nl" } - }; + const char* word; + const char* disp; + } words[] = {{"\"Foo Bar\" ", "Foo Bar"}, + {"Foo Bar ", "Foo Bar"}, + {"", "aap@noot.mies"}, + {"foo@bar.nl", "foo@bar.nl"}}; for (i = 0; i != G_N_ELEMENTS(words); ++i) - g_assert_cmpstr (mu_str_display_contact_s (words[i].word), ==, - words[i].disp); + g_assert_cmpstr(mu_str_display_contact_s(words[i].word), ==, words[i].disp); } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); /* mu_msg_str_date */ - g_test_add_func ("/mu-msg/mu-msg-01", - test_mu_msg_01); - g_test_add_func ("/mu-msg/mu-msg-02", - test_mu_msg_02); - g_test_add_func ("/mu-msg/mu-msg-03", - test_mu_msg_03); - g_test_add_func ("/mu-msg/mu-msg-04", - test_mu_msg_04); - g_test_add_func ("/mu-msg/mu-msg-multimime", - test_mu_msg_multimime); + g_test_add_func("/mu-msg/mu-msg-01", test_mu_msg_01); + g_test_add_func("/mu-msg/mu-msg-02", test_mu_msg_02); + g_test_add_func("/mu-msg/mu-msg-03", test_mu_msg_03); + g_test_add_func("/mu-msg/mu-msg-04", test_mu_msg_04); + g_test_add_func("/mu-msg/mu-msg-multimime", test_mu_msg_multimime); - g_test_add_func ("/mu-msg/mu-msg-flags", - test_mu_msg_flags); + g_test_add_func("/mu-msg/mu-msg-flags", test_mu_msg_flags); - g_test_add_func ("/mu-msg/mu-msg-tags", - test_mu_msg_tags); - g_test_add_func ("/mu-msg/mu-msg-references", - test_mu_msg_references); - g_test_add_func ("/mu-msg/mu-msg-references_dups", - test_mu_msg_references_dups); - g_test_add_func ("/mu-msg/mu-msg-references_many", - test_mu_msg_references_many); + g_test_add_func("/mu-msg/mu-msg-tags", test_mu_msg_tags); + g_test_add_func("/mu-msg/mu-msg-references", test_mu_msg_references); + g_test_add_func("/mu-msg/mu-msg-references_dups", test_mu_msg_references_dups); + g_test_add_func("/mu-msg/mu-msg-references_many", test_mu_msg_references_many); - g_test_add_func ("/mu-msg/mu-msg-umlaut", - test_mu_msg_umlaut); - g_test_add_func ("/mu-msg/mu-msg-comp-unix-programmer", - test_mu_msg_comp_unix_programmer); + g_test_add_func("/mu-msg/mu-msg-umlaut", test_mu_msg_umlaut); + g_test_add_func("/mu-msg/mu-msg-comp-unix-programmer", test_mu_msg_comp_unix_programmer); /* mu_str_prio */ - g_test_add_func ("/mu-str/mu-str-prio-01", - test_mu_str_prio_01); - g_test_add_func ("/mu-str/mu-str-prio-02", - test_mu_str_prio_02); + g_test_add_func("/mu-str/mu-str-prio-01", test_mu_str_prio_01); + g_test_add_func("/mu-str/mu-str-prio-02", test_mu_str_prio_02); + g_test_add_func("/mu-str/mu-str-display_contact", test_mu_str_display_contact); - g_test_add_func ("/mu-str/mu-str-display_contact", - test_mu_str_display_contact); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| - G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); - - rv = g_test_run (); + rv = g_test_run(); return rv; } diff --git a/lib/test-mu-store.cc b/lib/test-mu-store.cc index ca38123e..07794211 100644 --- a/lib/test-mu-store.cc +++ b/lib/test-mu-store.cc @@ -29,101 +29,101 @@ #include "test-mu-common.hh" #include "mu-store.hh" -static std::string MuTestMaildir = Mu::canonicalize_filename(MU_TESTMAILDIR, "/"); +static std::string MuTestMaildir = Mu::canonicalize_filename(MU_TESTMAILDIR, "/"); static std::string MuTestMaildir2 = Mu::canonicalize_filename(MU_TESTMAILDIR2, "/"); static void -test_store_ctor_dtor () +test_store_ctor_dtor() { - char *tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (tmpdir); + char* tmpdir = test_mu_common_get_random_tmpdir(); + g_assert(tmpdir); Mu::Store store{tmpdir, "/tmp", {}, {}}; - g_free (tmpdir); - g_assert_true(store.empty()); - g_assert_cmpuint (0,==,store.size()); + g_free(tmpdir); + g_assert_true(store.empty()); + g_assert_cmpuint(0, ==, store.size()); - g_assert_cmpstr (MU_STORE_SCHEMA_VERSION,==, - store.metadata().schema_version.c_str()); + g_assert_cmpstr(MU_STORE_SCHEMA_VERSION, ==, store.metadata().schema_version.c_str()); } static void -test_store_add_count_remove () +test_store_add_count_remove() { - char *tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (tmpdir); + char* tmpdir = test_mu_common_get_random_tmpdir(); + g_assert(tmpdir); Mu::Store store{tmpdir, MuTestMaildir, {}, {}}; - g_free (tmpdir); + g_free(tmpdir); - const auto id1 = store.add_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,"); + const auto id1 = store.add_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,"); - g_assert_cmpuint(id1, !=, Mu::Store::InvalidId); + g_assert_cmpuint(id1, !=, Mu::Store::InvalidId); - g_assert_cmpuint(store.size(), ==, 1); - g_assert_true(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); + g_assert_cmpuint(store.size(), ==, 1); + g_assert_true(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); - g_assert_cmpuint(store.add_message(MuTestMaildir2 + "/bar/cur/mail3"), - !=, Mu::Store::InvalidId); + g_assert_cmpuint(store.add_message(MuTestMaildir2 + "/bar/cur/mail3"), + !=, + Mu::Store::InvalidId); - g_assert_cmpuint(store.size(), ==, 2); - g_assert_true(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); + g_assert_cmpuint(store.size(), ==, 2); + g_assert_true(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); - store.remove_message(id1); - g_assert_cmpuint(store.size(), ==, 1); - g_assert_false(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); + store.remove_message(id1); + g_assert_cmpuint(store.size(), ==, 1); + g_assert_false( + store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); - store.remove_message (MuTestMaildir2 + "/bar/cur/mail3"); - g_assert_true(store.empty()); - g_assert_false(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); + store.remove_message(MuTestMaildir2 + "/bar/cur/mail3"); + g_assert_true(store.empty()); + g_assert_false(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); } - static void -test_store_add_count_remove_in_memory () +test_store_add_count_remove_in_memory() { Mu::Store store{MuTestMaildir, {}, {}}; - g_assert_true (store.metadata().in_memory); + g_assert_true(store.metadata().in_memory); - const auto id1 = store.add_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,"); + const auto id1 = store.add_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,"); - g_assert_cmpuint(id1, !=, Mu::Store::InvalidId); + g_assert_cmpuint(id1, !=, Mu::Store::InvalidId); - g_assert_cmpuint(store.size(), ==, 1); - g_assert_true(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); + g_assert_cmpuint(store.size(), ==, 1); + g_assert_true(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); - g_assert_cmpuint(store.add_message(MuTestMaildir2 + "/bar/cur/mail3"), - !=, Mu::Store::InvalidId); + g_assert_cmpuint(store.add_message(MuTestMaildir2 + "/bar/cur/mail3"), + !=, + Mu::Store::InvalidId); - g_assert_cmpuint(store.size(), ==, 2); - g_assert_true(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); + g_assert_cmpuint(store.size(), ==, 2); + g_assert_true(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); - store.remove_message(id1); - g_assert_cmpuint(store.size(), ==, 1); - g_assert_false(store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); + store.remove_message(id1); + g_assert_cmpuint(store.size(), ==, 1); + g_assert_false( + store.contains_message(MuTestMaildir + "/cur/1283599333.1840_11.cthulhu!2,")); - store.remove_message (MuTestMaildir2 + "/bar/cur/mail3"); - g_assert_true(store.empty()); - g_assert_false(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); + store.remove_message(MuTestMaildir2 + "/bar/cur/mail3"); + g_assert_true(store.empty()); + g_assert_false(store.contains_message(MuTestMaildir2 + "/bar/cur/mail3")); } - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); /* mu_runtime_init/uninit */ - g_test_add_func ("/store/ctor-dtor", test_store_ctor_dtor); - g_test_add_func ("/store/add-count-remove", test_store_add_count_remove); - g_test_add_func ("/store/in-memory/add-count-remove", test_store_add_count_remove_in_memory); + g_test_add_func("/store/ctor-dtor", test_store_ctor_dtor); + g_test_add_func("/store/add-count-remove", test_store_add_count_remove); + g_test_add_func("/store/in-memory/add-count-remove", test_store_add_count_remove_in_memory); // if (!g_test_verbose()) // g_log_set_handler (NULL, // G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, // (GLogFunc)black_hole, NULL); - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-parser.cc b/lib/test-parser.cc index d35ed013..4459d69a 100644 --- a/lib/test-parser.cc +++ b/lib/test-parser.cc @@ -40,17 +40,16 @@ using CaseVec = std::vector; static void test_cases(const CaseVec& cases) { - char *tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (tmpdir); + char* tmpdir = test_mu_common_get_random_tmpdir(); + g_assert(tmpdir); Mu::Store dummy_store{tmpdir, "/tmp", {}, {}}; - g_free (tmpdir); + g_free(tmpdir); - Parser parser{dummy_store, Parser::Flags::UnitTest}; - - for (const auto& casus : cases ) { + Parser parser{dummy_store, Parser::Flags::UnitTest}; + for (const auto& casus : cases) { WarningVec warnings; - const auto tree = parser.parse (casus.expr, warnings); + const auto tree = parser.parse(casus.expr, warnings); std::stringstream ss; ss << tree; @@ -62,88 +61,76 @@ test_cases(const CaseVec& cases) std::cout << "got:" << ss.str() << std::endl; } - assert_equal (casus.expected, ss.str()); + assert_equal(casus.expected, ss.str()); } } static void -test_basic () +test_basic() { CaseVec cases = { - //{ "", R"#((atom :value ""))#"}, - { "foo", R"#((value "msgid" "foo"))#", }, - { "foo or bar", - R"#((or(value "msgid" "foo")(value "msgid" "bar")))#" }, - { "foo and bar", - R"#((and(value "msgid" "foo")(value "msgid" "bar")))#"}, + //{ "", R"#((atom :value ""))#"}, + { + "foo", + R"#((value "msgid" "foo"))#", + }, + {"foo or bar", R"#((or(value "msgid" "foo")(value "msgid" "bar")))#"}, + {"foo and bar", R"#((and(value "msgid" "foo")(value "msgid" "bar")))#"}, }; - test_cases (cases); + test_cases(cases); } static void -test_complex () +test_complex() { CaseVec cases = { - { "foo and bar or cuux", - R"#((or(and(value "msgid" "foo")(value "msgid" "bar")))#" + - std::string(R"#((value "msgid" "cuux")))#") }, - { "a and not b", - R"#((and(value "msgid" "a")(not(value "msgid" "b"))))#" - }, - { "a and b and c", - R"#((and(value "msgid" "a")(and(value "msgid" "b")(value "msgid" "c"))))#" - }, - { "(a or b) and c", - R"#((and(or(value "msgid" "a")(value "msgid" "b"))(value "msgid" "c")))#" - }, - { "a b", // implicit and - R"#((and(value "msgid" "a")(value "msgid" "b")))#" - }, - { "a not b", // implicit and not - R"#((and(value "msgid" "a")(not(value "msgid" "b"))))#" - }, - { "not b", // implicit and not - R"#((not(value "msgid" "b")))#" - } - }; + {"foo and bar or cuux", + R"#((or(and(value "msgid" "foo")(value "msgid" "bar")))#" + + std::string(R"#((value "msgid" "cuux")))#")}, + {"a and not b", R"#((and(value "msgid" "a")(not(value "msgid" "b"))))#"}, + {"a and b and c", + R"#((and(value "msgid" "a")(and(value "msgid" "b")(value "msgid" "c"))))#"}, + {"(a or b) and c", + R"#((and(or(value "msgid" "a")(value "msgid" "b"))(value "msgid" "c")))#"}, + {"a b", // implicit and + R"#((and(value "msgid" "a")(value "msgid" "b")))#"}, + {"a not b", // implicit and not + R"#((and(value "msgid" "a")(not(value "msgid" "b"))))#"}, + {"not b", // implicit and not + R"#((not(value "msgid" "b")))#"}}; - test_cases (cases); + test_cases(cases); } - G_GNUC_UNUSED static void -test_range () +test_range() { CaseVec cases = { - { "range:a..b", // implicit and - R"#((range "range" "a" "b"))#" - }, + {"range:a..b", // implicit and + R"#((range "range" "a" "b"))#"}, }; - test_cases (cases); + test_cases(cases); } - static void -test_flatten () +test_flatten() { - CaseVec cases = { - { " Mötørhęåđ", R"#((value "msgid" "motorhead"))#" } - }; + CaseVec cases = {{" Mötørhęåđ", R"#((value "msgid" "motorhead"))#"}}; - test_cases (cases); + test_cases(cases); } int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/parser/basic", test_basic); - g_test_add_func ("/parser/complex", test_complex); - //g_test_add_func ("/parser/range", test_range); - g_test_add_func ("/parser/flatten", test_flatten); + g_test_add_func("/parser/basic", test_basic); + g_test_add_func("/parser/complex", test_complex); + // g_test_add_func ("/parser/range", test_range); + g_test_add_func("/parser/flatten", test_flatten); - return g_test_run (); + return g_test_run(); } diff --git a/lib/test-query.cc b/lib/test-query.cc index ce2c82bc..7f587cce 100644 --- a/lib/test-query.cc +++ b/lib/test-query.cc @@ -36,56 +36,60 @@ using namespace Mu; static void test_query() { - allow_warnings(); + allow_warnings(); + char* tdir; - Store store{test_mu_common_get_random_tmpdir(), std::string{MU_TESTMAILDIR}, {},{}}; - auto&& idx{store.indexer()}; + tdir = test_mu_common_get_random_tmpdir(); + Store store{tdir, std::string{MU_TESTMAILDIR}, {}, {}}; + g_free(tdir); - g_assert_true (idx.start(Indexer::Config{})); - while (idx.is_running()) { - sleep(1); - } + auto&& idx{store.indexer()}; - auto dump_matches=[](const QueryResults& res) { - size_t n{}; - for (auto&& item: res) - g_debug ("%02zu %s %s", ++n, item.path().value_or("").c_str(), - item.message_id().value_or("").c_str()); - }; + g_assert_true(idx.start(Indexer::Config{})); + while (idx.is_running()) { + sleep(1); + } + auto dump_matches = [](const QueryResults& res) { + size_t n{}; + for (auto&& item : res) + g_debug("%02zu %s %s", + ++n, + item.path().value_or("").c_str(), + item.message_id().value_or("").c_str()); + }; - Query q{store}; - g_assert_cmpuint(store.size(),==,19); + Query q{store}; + g_assert_cmpuint(store.size(), ==, 19); - { - const auto res = q.run("", MU_MSG_FIELD_ID_NONE, QueryFlags::None); - g_assert_true(!!res); - g_assert_cmpuint(res->size(),==,19); - dump_matches(*res); - } + { + const auto res = q.run("", MU_MSG_FIELD_ID_NONE, QueryFlags::None); + g_assert_true(!!res); + g_assert_cmpuint(res->size(), ==, 19); + dump_matches(*res); + } - { - const auto res = q.run("", MU_MSG_FIELD_ID_PATH, QueryFlags::None, 11); - g_assert_true(!!res); - g_assert_cmpuint(res->size(),==,11); - dump_matches(*res); - } + { + const auto res = q.run("", MU_MSG_FIELD_ID_PATH, QueryFlags::None, 11); + g_assert_true(!!res); + g_assert_cmpuint(res->size(), ==, 11); + dump_matches(*res); + } } int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/query", test_query); - - return g_test_run (); + g_test_add_func("/query", test_query); + return g_test_run(); } catch (const std::runtime_error& re) { std::cerr << re.what() << "\n"; return 1; } catch (...) { - std::cerr << "caught exception\n"; - return 1; + std::cerr << "caught exception\n"; + return 1; } diff --git a/lib/test-tokenizer.cc b/lib/test-tokenizer.cc index 5bfaf842..6e287f0e 100644 --- a/lib/test-tokenizer.cc +++ b/lib/test-tokenizer.cc @@ -25,7 +25,7 @@ #include "mu-tokenizer.hh" struct Case { - const char *str; + const char* str; const Mu::Tokens tokens; }; @@ -37,122 +37,111 @@ using TT = Token::Type; static void test_cases(const CaseVec& cases) { - for (const auto& casus : cases ) { - const auto tokens = tokenize (casus.str); + for (const auto& casus : cases) { + const auto tokens = tokenize(casus.str); - g_assert_cmpuint ((guint)tokens.size(),==,(guint)casus.tokens.size()); + g_assert_cmpuint((guint)tokens.size(), ==, (guint)casus.tokens.size()); for (size_t u = 0; u != tokens.size(); ++u) { if (g_test_verbose()) { std::cerr << "case " << u << " " << casus.str << std::endl; std::cerr << "exp: '" << casus.tokens[u] << "'" << std::endl; std::cerr << "got: '" << tokens[u] << "'" << std::endl; - } - g_assert_true (tokens[u] == casus.tokens[u]); + g_assert_true(tokens[u] == casus.tokens[u]); } } } static void -test_basic () +test_basic() { CaseVec cases = { - { "", {} }, + {"", {}}, - { "foo", Tokens{Token{3, TT::Data, "foo"}}}, + {"foo", Tokens{Token{3, TT::Data, "foo"}}}, - { "foo bar cuux", Tokens{Token{3, TT::Data, "foo"}, - Token{7, TT::Data, "bar"}, - Token{12, TT::Data, "cuux"}}}, + {"foo bar cuux", + Tokens{Token{3, TT::Data, "foo"}, + Token{7, TT::Data, "bar"}, + Token{12, TT::Data, "cuux"}}}, - { "\"foo bar\"", Tokens{ Token{9, TT::Data, "foo bar"}}}, + {"\"foo bar\"", Tokens{Token{9, TT::Data, "foo bar"}}}, - // ie. ignore missing closing '"' - { "\"foo bar", Tokens{ Token{8, TT::Data, "foo bar"}}}, + // ie. ignore missing closing '"' + {"\"foo bar", Tokens{Token{8, TT::Data, "foo bar"}}}, }; - test_cases (cases); + test_cases(cases); } static void -test_specials () +test_specials() { CaseVec cases = { - { ")*(", Tokens{Token{1, TT::Close, ")"}, - Token{2, TT::Data, "*"}, - Token{3, TT::Open, "("}}}, - { "\")*(\"", Tokens{Token{5, TT::Data, ")*("}}}, + {")*(", + Tokens{Token{1, TT::Close, ")"}, Token{2, TT::Data, "*"}, Token{3, TT::Open, "("}}}, + {"\")*(\"", Tokens{Token{5, TT::Data, ")*("}}}, }; - test_cases (cases); + test_cases(cases); } - static void -test_ops () +test_ops() { - CaseVec cases = { - { "foo and bar oR cuux XoR fnorb", - Tokens{Token{3, TT::Data, "foo"}, - Token{7, TT::And, "and"}, - Token{11, TT::Data, "bar"}, - Token{14, TT::Or, "oR"}, - Token{19, TT::Data, "cuux"}, - Token{23, TT::Xor, "XoR"}, - Token{29, TT::Data, "fnorb"}}}, - { "NOT (aap or mies)", - Tokens{Token{3, TT::Not, "NOT"}, - Token{5, TT::Open, "("}, - Token{8, TT::Data, "aap"}, - Token{11, TT::Or, "or"}, - Token{16, TT::Data, "mies"}, - Token{17, TT::Close, ")"}}} - }; + CaseVec cases = {{"foo and bar oR cuux XoR fnorb", + Tokens{Token{3, TT::Data, "foo"}, + Token{7, TT::And, "and"}, + Token{11, TT::Data, "bar"}, + Token{14, TT::Or, "oR"}, + Token{19, TT::Data, "cuux"}, + Token{23, TT::Xor, "XoR"}, + Token{29, TT::Data, "fnorb"}}}, + {"NOT (aap or mies)", + Tokens{Token{3, TT::Not, "NOT"}, + Token{5, TT::Open, "("}, + Token{8, TT::Data, "aap"}, + Token{11, TT::Or, "or"}, + Token{16, TT::Data, "mies"}, + Token{17, TT::Close, ")"}}}}; - - test_cases (cases); + test_cases(cases); } - static void -test_escape () +test_escape() { - CaseVec cases = { - { "foo\"bar\"", Tokens{Token{8, TT::Data, "foobar"}}}, - { "\"fnorb\"", Tokens{Token{7, TT::Data, "fnorb"}}}, - { "\\\"fnorb\\\"", Tokens{Token{9, TT::Data, "fnorb"}}}, - { "foo\\\"bar\\\"", Tokens{Token{10, TT::Data, "foobar"}}} - }; + CaseVec cases = {{"foo\"bar\"", Tokens{Token{8, TT::Data, "foobar"}}}, + {"\"fnorb\"", Tokens{Token{7, TT::Data, "fnorb"}}}, + {"\\\"fnorb\\\"", Tokens{Token{9, TT::Data, "fnorb"}}}, + {"foo\\\"bar\\\"", Tokens{Token{10, TT::Data, "foobar"}}}}; - test_cases (cases); + test_cases(cases); } - static void -test_to_string () +test_to_string() { std::stringstream ss; - for (auto&& t: tokenize ("foo and bar xor not cuux or fnorb")) + for (auto&& t : tokenize("foo and bar xor not cuux or fnorb")) ss << t << ' '; - g_assert_true (ss.str() == - "3: [foo] 7: [and] 11: [bar] " - "15: [xor] 19: [not] 24: [cuux] " - "27: [or] 33: [fnorb] "); + g_assert_true(ss.str() == "3: [foo] 7: [and] 11: [bar] " + "15: [xor] 19: [not] 24: [cuux] " + "27: [or] 33: [fnorb] "); } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/tokens/basic", test_basic); - g_test_add_func ("/tokens/specials", test_specials); - g_test_add_func ("/tokens/ops", test_ops); - g_test_add_func ("/tokens/escape", test_escape); - g_test_add_func ("/tokens/to-string", test_to_string); + g_test_add_func("/tokens/basic", test_basic); + g_test_add_func("/tokens/specials", test_specials); + g_test_add_func("/tokens/ops", test_ops); + g_test_add_func("/tokens/escape", test_escape); + g_test_add_func("/tokens/to-string", test_to_string); - return g_test_run (); + return g_test_run(); } diff --git a/lib/tokenize.cc b/lib/tokenize.cc index 81f6ef06..96a87087 100644 --- a/lib/tokenize.cc +++ b/lib/tokenize.cc @@ -23,14 +23,14 @@ #include "mu-tokenizer.hh" int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { std::string s; for (auto i = 1; i < argc; ++i) s += " " + std::string(argv[i]); - const auto tvec = Mu::tokenize (s); + const auto tvec = Mu::tokenize(s); for (const auto& t : tvec) std::cout << t << std::endl; diff --git a/lib/utils/mu-async-queue.hh b/lib/utils/mu-async-queue.hh index ddd6841e..fe034982 100644 --- a/lib/utils/mu-async-queue.hh +++ b/lib/utils/mu-async-queue.hh @@ -29,163 +29,166 @@ namespace Mu { constexpr std::size_t UnlimitedAsyncQueueSize{0}; -template > /**< allocator the items */ class AsyncQueue { -public: - using value_type = ItemType; - using allocator_type = Allocator; - using size_type = std::size_t; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = typename std::allocator_traits::pointer; - using const_pointer = typename std::allocator_traits::const_pointer; + public: + using value_type = ItemType; + using allocator_type = Allocator; + using size_type = std::size_t; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = typename std::allocator_traits::pointer; + using const_pointer = typename std::allocator_traits::const_pointer; - using Timeout = std::chrono::steady_clock::duration; + using Timeout = std::chrono::steady_clock::duration; - #define LOCKED std::unique_lock lock(m_); +#define LOCKED std::unique_lock lock(m_); - bool push (const value_type& item, Timeout timeout = {}) { - return push(std::move(value_type(item))); - } + bool push(const value_type& item, Timeout timeout = {}) + { + return push(std::move(value_type(item))); + } - /** - * Push an item to the end of the queue by moving it - * - * @param item the item to move to the end of the queue - * @param timeout and optional timeout - * - * @return true if the item was pushed; false otherwise. - */ - bool push (value_type&& item, Timeout timeout = {}) { + /** + * Push an item to the end of the queue by moving it + * + * @param item the item to move to the end of the queue + * @param timeout and optional timeout + * + * @return true if the item was pushed; false otherwise. + */ + bool push(value_type&& item, Timeout timeout = {}) + { + LOCKED; - LOCKED; + if (!unlimited()) { + const auto rv = cv_full_.wait_for(lock, timeout, [&]() { + return !full_unlocked(); + }) && !full_unlocked(); + if (!rv) + return false; + } - if (!unlimited()) { - const auto rv = cv_full_.wait_for(lock, timeout,[&](){ - return !full_unlocked();}) && !full_unlocked(); - if (!rv) - return false; - } + q_.emplace_back(std::move(item)); + lock.unlock(); - q_.emplace_back(std::move(item)); - lock.unlock(); + cv_empty_.notify_one(); + return true; + } - cv_empty_.notify_one(); - return true; + /** + * Pop an item from the queue + * + * @param receives the value if the function returns true + * @param timeout optional time to wait for an item to become available + * + * @return true if an item was popped (into val), false otherwise. + */ + bool pop(value_type& val, Timeout timeout = {}) + { + LOCKED; - } + if (timeout != Timeout{}) { + const auto rv = cv_empty_.wait_for(lock, timeout, [&]() { + return !q_.empty(); + }) && !q_.empty(); + if (!rv) + return false; - /** - * Pop an item from the queue - * - * @param receives the value if the function returns true - * @param timeout optional time to wait for an item to become available - * - * @return true if an item was popped (into val), false otherwise. - */ - bool pop (value_type& val, Timeout timeout = {}) { + } else if (q_.empty()) + return false; - LOCKED; + val = std::move(q_.front()); + q_.pop_front(); + lock.unlock(); + cv_full_.notify_one(); - if (timeout != Timeout{}) { - const auto rv = cv_empty_.wait_for(lock, timeout,[&](){ - return !q_.empty(); }) && !q_.empty(); - if (!rv) - return false; + return true; + } - } else if (q_.empty()) - return false; + /** + * Clear the queue + * + */ + void clear() + { + LOCKED; + q_.clear(); + lock.unlock(); + cv_full_.notify_one(); + } - val = std::move(q_.front()); - q_.pop_front(); - lock.unlock(); - cv_full_.notify_one(); + /** + * Size of the queue + * + * + * @return the size + */ + size_type size() const + { + LOCKED; + return q_.size(); + } - return true; - } + /** + * Maximum size of the queue if specified through the template + * parameter; otherwise the (theoretical) max_size of the inner + * container. + * + * @return the maximum size + */ + size_type max_size() const + { + if (unlimited()) + return q_.max_size(); + else + return MaxSize; + } - /** - * Clear the queue - * - */ - void clear() { - LOCKED; - q_.clear(); - lock.unlock(); - cv_full_.notify_one(); - } + /** + * Is the queue empty? + * + * @return true or false + */ + bool empty() const + { + LOCKED; + return q_.empty(); + } - /** - * Size of the queue - * - * - * @return the size - */ - size_type size() const { - LOCKED; - return q_.size(); - } + /** + * Is the queue full? Returns false unless a maximum size was specified + * (as a template argument) + * + * @return true or false. + */ + bool full() const + { + if (unlimited()) + return false; - /** - * Maximum size of the queue if specified through the template - * parameter; otherwise the (theoretical) max_size of the inner - * container. - * - * @return the maximum size - */ - size_type max_size() const { - if (unlimited()) - return q_.max_size(); - else - return MaxSize; - } + LOCKED; + return full_unlocked(); + } - /** - * Is the queue empty? - * - * @return true or false - */ - bool empty() const { - LOCKED; - return q_.empty(); - } + /** + * Is this queue (theoretically) unlimited in size? + * + * @return true or false + */ + constexpr static bool unlimited() { return MaxSize == UnlimitedAsyncQueueSize; } - /** - * Is the queue full? Returns false unless a maximum size was specified - * (as a template argument) - * - * @return true or false. - */ - bool full() const { - if (unlimited()) - return false; + private: + bool full_unlocked() const { return q_.size() >= max_size(); } - LOCKED; - return full_unlocked(); - } - - /** - * Is this queue (theoretically) unlimited in size? - * - * @return true or false - */ - constexpr static bool unlimited() { - return MaxSize == UnlimitedAsyncQueueSize; - } - -private: - bool full_unlocked() const { - return q_.size() >= max_size(); - } - - std::deque q_; - mutable std::mutex m_; - std::condition_variable cv_full_, cv_empty_; + std::deque q_; + mutable std::mutex m_; + std::condition_variable cv_full_, cv_empty_; }; -} // namespace mu +} // namespace Mu #endif /* __MU_ASYNC_QUEUE_HH__ */ diff --git a/lib/utils/mu-command-parser.cc b/lib/utils/mu-command-parser.cc index bf4193d9..97271741 100644 --- a/lib/utils/mu-command-parser.cc +++ b/lib/utils/mu-command-parser.cc @@ -30,170 +30,165 @@ using namespace Command; void Command::invoke(const Command::CommandMap& cmap, const Sexp& call) { - if (!call.is_call()) { - throw Mu::Error{Error::Code::Command, - "expected call-sexpr but got %s", - call.to_sexp_string().c_str()}; - } + if (!call.is_call()) { + throw Mu::Error{Error::Code::Command, + "expected call-sexpr but got %s", + call.to_sexp_string().c_str()}; + } - const auto& params{call.list()}; - const auto cmd_it = cmap.find(params.at(0).value()); - if (cmd_it == cmap.end()) - throw Mu::Error{Error::Code::Command, - "unknown command in call %s", - call.to_sexp_string().c_str()}; + const auto& params{call.list()}; + const auto cmd_it = cmap.find(params.at(0).value()); + if (cmd_it == cmap.end()) + throw Mu::Error{Error::Code::Command, + "unknown command in call %s", + call.to_sexp_string().c_str()}; - const auto& cinfo{cmd_it->second}; + const auto& cinfo{cmd_it->second}; - // all required parameters must be present - for (auto&& arg: cinfo.args) { - const auto& argname{arg.first}; - const auto& arginfo{arg.second}; + // all required parameters must be present + for (auto&& arg : cinfo.args) { + const auto& argname{arg.first}; + const auto& arginfo{arg.second}; - // calls used keyword-parameters, e.g. - // (my-function :bar 1 :cuux "fnorb") - // so, we're looking for the odd-numbered parameters. - const auto param_it = [&]()->Sexp::Seq::const_iterator { - for (size_t i = 1; i < params.size(); i += 2) - if (params.at(i).is_symbol() && params.at(i).value() == argname) - return params.begin() + i + 1; + // calls used keyword-parameters, e.g. + // (my-function :bar 1 :cuux "fnorb") + // so, we're looking for the odd-numbered parameters. + const auto param_it = [&]() -> Sexp::Seq::const_iterator { + for (size_t i = 1; i < params.size(); i += 2) + if (params.at(i).is_symbol() && params.at(i).value() == argname) + return params.begin() + i + 1; - return params.end(); + return params.end(); + }(); - }(); + // it's an error when a required parameter is missing. + if (param_it == params.end()) { + if (arginfo.required) + throw Mu::Error{Error::Code::Command, + "missing required parameter %s in call %s", + argname.c_str(), + call.to_sexp_string().c_str()}; + continue; // not required + } - // it's an error when a required parameter is missing. - if (param_it == params.end()) { - if (arginfo.required) - throw Mu::Error{Error::Code::Command, - "missing required parameter %s in call %s", - argname.c_str(), call.to_sexp_string().c_str()}; - continue; // not required - } + // the types must match, but the 'nil' symbol is acceptable as + // "no value" + if (param_it->type() != arginfo.type && !(param_it->is_nil())) + throw Mu::Error{Error::Code::Command, + "parameter %s expects type %s, but got %s in call %s", + argname.c_str(), + to_string(arginfo.type).c_str(), + to_string(param_it->type()).c_str(), + call.to_sexp_string().c_str()}; + } - // the types must match, but the 'nil' symbol is acceptable as - // "no value" - if (param_it->type() != arginfo.type && !(param_it->is_nil())) - throw Mu::Error{Error::Code::Command, - "parameter %s expects type %s, but got %s in call %s", - argname.c_str(), to_string(arginfo.type).c_str(), - to_string(param_it->type()).c_str(), - call.to_sexp_string().c_str()}; - } + // all passed parameters must be known + for (size_t i = 1; i < params.size(); i += 2) { + if (std::none_of(cinfo.args.begin(), cinfo.args.end(), [&](auto&& arg) { + return params.at(i).value() == arg.first; + })) + throw Mu::Error{Error::Code::Command, + "unknown parameter %s in call %s", + params.at(i).value().c_str(), + call.to_sexp_string().c_str()}; + } - // all passed parameters must be known - for (size_t i = 1; i < params.size(); i += 2) { - if (std::none_of(cinfo.args.begin(), cinfo.args.end(), - [&](auto&& arg) {return params.at(i).value() == arg.first;})) - throw Mu::Error{Error::Code::Command, - "unknown parameter %s in call %s", - params.at(i).value().c_str(), call.to_sexp_string().c_str()}; - } - - if (cinfo.handler) - cinfo.handler(params); + if (cinfo.handler) + cinfo.handler(params); } static Sexp::Seq::const_iterator -find_param_node (const Parameters& params, const std::string& argname) +find_param_node(const Parameters& params, const std::string& argname) { - if (params.empty()) - throw Error(Error::Code::InvalidArgument, - "params must not be empty"); + if (params.empty()) + throw Error(Error::Code::InvalidArgument, "params must not be empty"); - if (argname.empty() || argname.at(0) != ':') - throw Error(Error::Code::InvalidArgument, - "property key must start with ':' but got '%s')", - argname.c_str()); + if (argname.empty() || argname.at(0) != ':') + throw Error(Error::Code::InvalidArgument, + "property key must start with ':' but got '%s')", + argname.c_str()); - for (size_t i = 1; i < params.size(); i += 2) { - if (i + 1 != params.size() && - params.at(i).is_symbol() && params.at(i).value() == argname) - return params.begin() + i + 1; - } + for (size_t i = 1; i < params.size(); i += 2) { + if (i + 1 != params.size() && params.at(i).is_symbol() && + params.at(i).value() == argname) + return params.begin() + i + 1; + } - return params.end(); + return params.end(); } - static Error -wrong_type (Sexp::Type expected, Sexp::Type got) +wrong_type(Sexp::Type expected, Sexp::Type got) { - return Error(Error::Code::InvalidArgument, - "expected <%s> but got <%s>", - to_string(expected).c_str(), - to_string(got).c_str()); -} - - -const std::string& -Command::get_string_or (const Parameters& params, const std::string& argname, - const std::string& alt) -{ - const auto it = find_param_node (params, argname); - if (it == params.end() || it->is_nil()) - return alt; - else if (!it->is_string()) - throw wrong_type(Sexp::Type::String, it->type()); - else - return it->value(); + return Error(Error::Code::InvalidArgument, + "expected <%s> but got <%s>", + to_string(expected).c_str(), + to_string(got).c_str()); } const std::string& -Command::get_symbol_or (const Parameters& params, const std::string& argname, - const std::string& alt) +Command::get_string_or(const Parameters& params, const std::string& argname, const std::string& alt) { - const auto it = find_param_node (params, argname); - if (it == params.end() || it->is_nil()) - return alt; - else if (!it->is_symbol()) - throw wrong_type(Sexp::Type::Symbol, it->type()); - else - return it->value(); + const auto it = find_param_node(params, argname); + if (it == params.end() || it->is_nil()) + return alt; + else if (!it->is_string()) + throw wrong_type(Sexp::Type::String, it->type()); + else + return it->value(); } +const std::string& +Command::get_symbol_or(const Parameters& params, const std::string& argname, const std::string& alt) +{ + const auto it = find_param_node(params, argname); + if (it == params.end() || it->is_nil()) + return alt; + else if (!it->is_symbol()) + throw wrong_type(Sexp::Type::Symbol, it->type()); + else + return it->value(); +} int -Command::get_int_or (const Parameters& params, const std::string& argname, - int alt) +Command::get_int_or(const Parameters& params, const std::string& argname, int alt) { - const auto it = find_param_node (params, argname); - if (it == params.end() || it->is_nil()) - return alt; - else if (!it->is_number()) - throw wrong_type(Sexp::Type::Number, it->type()); - else - return ::atoi(it->value().c_str()); + const auto it = find_param_node(params, argname); + if (it == params.end() || it->is_nil()) + return alt; + else if (!it->is_number()) + throw wrong_type(Sexp::Type::Number, it->type()); + else + return ::atoi(it->value().c_str()); } bool -Command::get_bool_or (const Parameters& params, const std::string& argname, - bool alt) +Command::get_bool_or(const Parameters& params, const std::string& argname, bool alt) { - const auto it = find_param_node (params, argname); - if (it == params.end()) - return alt; - else if (!it->is_symbol()) - throw wrong_type(Sexp::Type::Symbol, it->type()); - else - return it->is_nil() ? false : true; + const auto it = find_param_node(params, argname); + if (it == params.end()) + return alt; + else if (!it->is_symbol()) + throw wrong_type(Sexp::Type::Symbol, it->type()); + else + return it->is_nil() ? false : true; } std::vector -Command::get_string_vec (const Parameters& params, const std::string& argname) +Command::get_string_vec(const Parameters& params, const std::string& argname) { - const auto it = find_param_node (params, argname); - if (it == params.end() || it->is_nil()) - return {}; - else if (!it->is_list()) - throw wrong_type(Sexp::Type::List, it->type()); + const auto it = find_param_node(params, argname); + if (it == params.end() || it->is_nil()) + return {}; + else if (!it->is_list()) + throw wrong_type(Sexp::Type::List, it->type()); - std::vector vec; - for (const auto& n: it->list()) { - if (!n.is_string()) - throw wrong_type(Sexp::Type::String, n.type()); - vec.emplace_back (n.value()); - } + std::vector vec; + for (const auto& n : it->list()) { + if (!n.is_string()) + throw wrong_type(Sexp::Type::String, n.type()); + vec.emplace_back(n.value()); + } - return vec; + return vec; } diff --git a/lib/utils/mu-command-parser.hh b/lib/utils/mu-command-parser.hh index de6e878a..a2ecebcb 100644 --- a/lib/utils/mu-command-parser.hh +++ b/lib/utils/mu-command-parser.hh @@ -30,7 +30,6 @@ #include "utils/mu-error.hh" #include "utils/mu-sexp.hh" - namespace Mu { namespace Command { @@ -46,63 +45,66 @@ namespace Command { /// for specify a non-required parameter to be absent; this is for convenience on the /// call side. - /// Information about a function argument struct ArgInfo { - ArgInfo (Sexp::Type typearg, bool requiredarg, std::string&& docarg): - type{typearg}, required{requiredarg},docstring{std::move(docarg)} - {} - const Sexp::Type type; /**< Sexp::Type of the argument */ - const bool required; /**< Is this argument required? */ - const std::string docstring; /**< Documentation */ + ArgInfo(Sexp::Type typearg, bool requiredarg, std::string&& docarg) + : type{typearg}, required{requiredarg}, docstring{std::move(docarg)} + { + } + const Sexp::Type type; /**< Sexp::Type of the argument */ + const bool required; /**< Is this argument required? */ + const std::string docstring; /**< Documentation */ }; /// The arguments for a function, which maps their names to the information. -using ArgMap = std::unordered_map; +using ArgMap = std::unordered_map; // The parameters to a Handler. using Parameters = Sexp::Seq; -int get_int_or (const Parameters& parms, const std::string& argname, int alt=0); -bool get_bool_or (const Parameters& parms, const std::string& argname, bool alt=false); -const std::string& get_string_or (const Parameters& parms, const std::string& argname, const std::string& alt=""); -const std::string& get_symbol_or (const Parameters& parms, const std::string& argname, const std::string& alt="nil"); - - -std::vector get_string_vec (const Parameters& params, const std::string& argname); +int get_int_or(const Parameters& parms, const std::string& argname, int alt = 0); +bool get_bool_or(const Parameters& parms, const std::string& argname, bool alt = false); +const std::string& +get_string_or(const Parameters& parms, const std::string& argname, const std::string& alt = ""); +const std::string& +get_symbol_or(const Parameters& parms, const std::string& argname, const std::string& alt = "nil"); +std::vector get_string_vec(const Parameters& params, const std::string& argname); // A handler function -using Handler = std::function; +using Handler = std::function; /// Information about some command struct CommandInfo { - CommandInfo(ArgMap&& argmaparg, std::string&& docarg, Handler&& handlerarg): - args{std::move(argmaparg)}, docstring{std::move(docarg)}, handler{std::move(handlerarg)} - {} - const ArgMap args; - const std::string docstring; - const Handler handler; + CommandInfo(ArgMap&& argmaparg, std::string&& docarg, Handler&& handlerarg) + : args{std::move(argmaparg)}, docstring{std::move(docarg)}, handler{ + std::move(handlerarg)} + { + } + const ArgMap args; + const std::string docstring; + const Handler handler; - /** - * Get a sorted list of argument names, for display. Required args come - * first, then alphabetical. - * - * @return vec with the sorted names. - */ - std::vector sorted_argnames() const { // sort args -- by required, then alphabetical. - std::vector names; - for (auto&& arg: args) - names.emplace_back(arg.first); - std::sort(names.begin(), names.end(), [&](const auto& name1, const auto& name2) { - const auto& arg1{args.find(name1)->second}; - const auto& arg2{args.find(name2)->second}; - if (arg1.required != arg2.required) - return arg1.required; - else - return name1 < name2; - }); - return names; - } + /** + * Get a sorted list of argument names, for display. Required args come + * first, then alphabetical. + * + * @return vec with the sorted names. + */ + std::vector sorted_argnames() const + { // sort args -- by required, then alphabetical. + std::vector names; + for (auto&& arg : args) + names.emplace_back(arg.first); + std::sort(names.begin(), names.end(), [&](const auto& name1, const auto& name2) { + const auto& arg1{args.find(name1)->second}; + const auto& arg2{args.find(name2)->second}; + if (arg1.required != arg2.required) + return arg1.required; + else + return name1 < name2; + }); + return names; + } }; /// All commands, mapping their name to information about them. using CommandMap = std::unordered_map; @@ -120,37 +122,34 @@ using CommandMap = std::unordered_map; */ void invoke(const Command::CommandMap& cmap, const Sexp& call); - static inline std::ostream& operator<<(std::ostream& os, const Command::ArgInfo& info) { - os << info.type - << " (" << ( info.required ? "required" : "optional" ) << ")"; + os << info.type << " (" << (info.required ? "required" : "optional") << ")"; - return os; + return os; } static inline std::ostream& operator<<(std::ostream& os, const Command::CommandInfo& info) { - for (auto&& arg: info.args) - os << " " << arg.first << " " << arg.second << '\n' - << " " << arg.second.docstring << "\n"; + for (auto&& arg : info.args) + os << " " << arg.first << " " << arg.second << '\n' + << " " << arg.second.docstring << "\n"; - return os; + return os; } static inline std::ostream& operator<<(std::ostream& os, const Command::CommandMap& map) { - for (auto&& c: map) - os << c.first << '\n' << c.second; + for (auto&& c : map) + os << c.first << '\n' << c.second; - return os; + return os; } } // namespace Command } // namespace Mu - #endif /* MU_COMMAND_PARSER_HH__ */ diff --git a/lib/utils/mu-error.hh b/lib/utils/mu-error.hh index 017bea8c..2b5ae9a1 100644 --- a/lib/utils/mu-error.hh +++ b/lib/utils/mu-error.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_ERROR_HH__ #define MU_ERROR_HH__ @@ -27,106 +26,101 @@ namespace Mu { -struct Error final: public std::exception { +struct Error final : public std::exception { + enum struct Code { + AccessDenied = 100, // don't overlap with MuError + Command, + File, + Index, + Internal, + InvalidArgument, + Message, + NotFound, + Parsing, + Query, + SchemaMismatch, + Store, + }; - enum struct Code { - AccessDenied = 100, // don't overlap with MuError - Command, - File, - Index, - Internal, - InvalidArgument, - Message, - NotFound, - Parsing, - Query, - SchemaMismatch, - Store, - }; + /** + * Construct an error + * + * @param codearg error-code + * #param msgarg the error diecription + */ + Error(Code codearg, const std::string& msgarg) : code_{codearg}, what_{msgarg} {} - /** - * Construct an error - * - * @param codearg error-code - * #param msgarg the error diecription - */ - Error(Code codearg, const std::string& msgarg): - code_{codearg}, what_{msgarg} - {} + /** + * Build an error from an error-code and a format string + * + * @param code error-code + * @param frm format string + * @param ... format parameters + * + * @return an Error object + */ + __attribute__((format(printf, 3, 0))) Error(Code codearg, const char* frm, ...) + : code_{codearg} + { + va_list args; + va_start(args, frm); + what_ = vformat(frm, args); + va_end(args); + } - /** - * Build an error from an error-code and a format string - * - * @param code error-code - * @param frm format string - * @param ... format parameters - * - * @return an Error object - */ - __attribute__((format(printf, 3, 0))) - Error(Code codearg, const char *frm, ...): code_{codearg} { - va_list args; - va_start(args, frm); - what_ = vformat(frm, args); - va_end(args); - } + Error(Error&& rhs) = default; + Error(const Error& rhs) = delete; - Error(Error&& rhs) = default; - Error(const Error& rhs) = delete; + /** + * Build an error from a GError an error-code and a format string + * + * @param code error-code + * @param gerr a GError or {}, which is consumed + * @param frm format string + * @param ... format parameters + * + * @return an Error object + */ + __attribute__((format(printf, 4, 0))) + Error(Code codearg, GError** err, const char* frm, ...) + : code_{codearg} + { + va_list args; + va_start(args, frm); + what_ = vformat(frm, args); + va_end(args); - /** - * Build an error from a GError an error-code and a format string - * - * @param code error-code - * @param gerr a GError or {}, which is consumed - * @param frm format string - * @param ... format parameters - * - * @return an Error object - */ - __attribute__((format(printf, 4, 0))) - Error(Code codearg, GError **err, const char *frm, ...): code_{codearg} { + if (err && *err) + what_ += format(": %s", (*err)->message); + else + what_ += ": something went wrong"; - va_list args; - va_start(args, frm); - what_ = vformat(frm, args); - va_end(args); + g_clear_error(err); + } - if (err && *err) - what_ += format (": %s", (*err)->message); - else - what_ += ": something went wrong"; + /** + * DTOR + * + */ + virtual ~Error() = default; - g_clear_error(err); - } + /** + * Get the descriptiove message. + * + * @return + */ + virtual const char* what() const noexcept override { return what_.c_str(); } - /** - * DTOR - * - */ - virtual ~Error() = default; + /** + * Get the error-code for this error + * + * @return the error-code + */ + Code code() const { return code_; } - /** - * Get the descriptiove message. - * - * @return - */ - virtual const char* what() const noexcept override { - return what_.c_str(); - } - - /** - * Get the error-code for this error - * - * @return the error-code - */ - Code code() const { return code_; } - - - -private: - const Code code_; - std::string what_; + private: + const Code code_; + std::string what_; }; } // namespace Mu diff --git a/lib/utils/mu-logger.cc b/lib/utils/mu-logger.cc index 01893891..b1f3a054 100644 --- a/lib/utils/mu-logger.cc +++ b/lib/utils/mu-logger.cc @@ -35,151 +35,145 @@ using namespace Mu; static bool MuLogInitialized = false; static Mu::LogOptions MuLogOptions; static std::ofstream MuStream; -static auto MaxLogFileSize = 1000 * 1024; +static auto MaxLogFileSize = 1000 * 1024; -static std::string MuLogPath; +static std::string MuLogPath; static bool -maybe_open_logfile () +maybe_open_logfile() { - if (MuStream.is_open()) - return true; + if (MuStream.is_open()) + return true; - MuStream.open (MuLogPath, std::ios::out | std::ios::app ); - if (!MuStream.is_open()) { - std::cerr << "opening " << MuLogPath << " failed:" - << g_strerror(errno) << std::endl; - return false; - } + MuStream.open(MuLogPath, std::ios::out | std::ios::app); + if (!MuStream.is_open()) { + std::cerr << "opening " << MuLogPath << " failed:" << g_strerror(errno) + << std::endl; + return false; + } - MuStream.sync_with_stdio(false); - return true; + MuStream.sync_with_stdio(false); + return true; } static bool -maybe_rotate_logfile () +maybe_rotate_logfile() { - static unsigned n = 0; + static unsigned n = 0; - if (n++ % 1000 != 0) - return true; + if (n++ % 1000 != 0) + return true; - GStatBuf statbuf; - if (g_stat(MuLogPath.c_str(), &statbuf) == -1 || - statbuf.st_size <= MaxLogFileSize) - return true; + GStatBuf statbuf; + if (g_stat(MuLogPath.c_str(), &statbuf) == -1 || statbuf.st_size <= MaxLogFileSize) + return true; - const auto old = MuLogPath + ".old"; - g_unlink(old.c_str()); // opportunistic + const auto old = MuLogPath + ".old"; + g_unlink(old.c_str()); // opportunistic - if (MuStream.is_open()) - MuStream.close(); + if (MuStream.is_open()) + MuStream.close(); - if (g_rename(MuLogPath.c_str(), old.c_str()) != 0) - std::cerr << "failed to rename " - << MuLogPath << " -> " << old.c_str() - << ": " << g_strerror(errno) << std::endl; + if (g_rename(MuLogPath.c_str(), old.c_str()) != 0) + std::cerr << "failed to rename " << MuLogPath << " -> " << old.c_str() << ": " + << g_strerror(errno) << std::endl; - return maybe_open_logfile(); + return maybe_open_logfile(); } static GLogWriterOutput -log_file (GLogLevelFlags level, const GLogField *fields, gsize n_fields, - gpointer user_data) +log_file(GLogLevelFlags level, const GLogField* fields, gsize n_fields, gpointer user_data) { - if (!maybe_open_logfile()) - return G_LOG_WRITER_UNHANDLED; + if (!maybe_open_logfile()) + return G_LOG_WRITER_UNHANDLED; - char timebuf[22]; - time_t now{::time(NULL)}; - ::strftime (timebuf, sizeof(timebuf), "%F %T", ::localtime(&now)); + char timebuf[22]; + time_t now{::time(NULL)}; + ::strftime(timebuf, sizeof(timebuf), "%F %T", ::localtime(&now)); - char *msg = g_log_writer_format_fields (level, fields, n_fields, FALSE); - if (msg && msg[0] == '\n') // hmm... seems lines start with '\n'r - msg[0] = ' '; + char* msg = g_log_writer_format_fields(level, fields, n_fields, FALSE); + if (msg && msg[0] == '\n') // hmm... seems lines start with '\n'r + msg[0] = ' '; - MuStream << timebuf << ' ' << msg << std::endl; + MuStream << timebuf << ' ' << msg << std::endl; - g_free (msg); + g_free(msg); - return maybe_rotate_logfile() ? G_LOG_WRITER_HANDLED : G_LOG_WRITER_UNHANDLED; + return maybe_rotate_logfile() ? G_LOG_WRITER_HANDLED : G_LOG_WRITER_UNHANDLED; } static GLogWriterOutput -log_stdouterr (GLogLevelFlags level, const GLogField *fields, gsize n_fields, - gpointer user_data) +log_stdouterr(GLogLevelFlags level, const GLogField* fields, gsize n_fields, gpointer user_data) { - return g_log_writer_standard_streams (level, fields, n_fields, user_data); + return g_log_writer_standard_streams(level, fields, n_fields, user_data); } static GLogWriterOutput -log_journal (GLogLevelFlags level, const GLogField *fields, gsize n_fields, - gpointer user_data) +log_journal(GLogLevelFlags level, const GLogField* fields, gsize n_fields, gpointer user_data) { - return g_log_writer_journald (level, fields, n_fields, user_data); + return g_log_writer_journald(level, fields, n_fields, user_data); } void -Mu::log_init (const std::string& path, Mu::LogOptions opts) +Mu::log_init(const std::string& path, Mu::LogOptions opts) { - if (MuLogInitialized) { - g_error ("logging is already initialized"); - return; - } + if (MuLogInitialized) { + g_error("logging is already initialized"); + return; + } - MuLogOptions = opts; - MuLogPath = path; + MuLogOptions = opts; + MuLogPath = path; - g_log_set_writer_func ( - [](GLogLevelFlags level, const GLogField *fields, gsize n_fields, - gpointer user_data) { + g_log_set_writer_func( + [](GLogLevelFlags level, const GLogField* fields, gsize n_fields, gpointer user_data) { + // filter out debug-level messages? + if (level == G_LOG_LEVEL_DEBUG && + (none_of(MuLogOptions & Mu::LogOptions::Debug))) + return G_LOG_WRITER_HANDLED; - // filter out debug-level messages? - if (level == G_LOG_LEVEL_DEBUG && - (none_of (MuLogOptions & Mu::LogOptions::Debug))) - return G_LOG_WRITER_HANDLED; + // log criticals to stdout / err or if asked + if (level == G_LOG_LEVEL_CRITICAL || + any_of(MuLogOptions & Mu::LogOptions::StdOutErr)) { + log_stdouterr(level, fields, n_fields, user_data); + } - // log criticals to stdout / err or if asked - if (level == G_LOG_LEVEL_CRITICAL || - any_of(MuLogOptions & Mu::LogOptions::StdOutErr)){ - log_stdouterr (level, fields, n_fields, user_data); - } + // log to the journal, or, if not available to a file. + if (log_journal(level, fields, n_fields, user_data) != G_LOG_WRITER_HANDLED) + return log_file(level, fields, n_fields, user_data); + else + return G_LOG_WRITER_HANDLED; + }, + NULL, + NULL); - // log to the journal, or, if not available to a file. - if (log_journal (level, fields, n_fields, user_data) != - G_LOG_WRITER_HANDLED) - return log_file (level, fields, n_fields, user_data); - else - return G_LOG_WRITER_HANDLED; - }, NULL, NULL); + g_message("logging initialized; debug: %s, stdout/stderr: %s", + any_of(log_get_options() & LogOptions::Debug) ? "yes" : "no", + any_of(log_get_options() & LogOptions::StdOutErr) ? "yes" : "no"); - g_message ("logging initialized; debug: %s, stdout/stderr: %s", - any_of(log_get_options() & LogOptions::Debug) ? "yes" : "no", - any_of(log_get_options() & LogOptions::StdOutErr) ? "yes" : "no"); - - MuLogInitialized = true; + MuLogInitialized = true; } void -Mu::log_uninit () +Mu::log_uninit() { - if (!MuLogInitialized) - return; + if (!MuLogInitialized) + return; - if (MuStream.is_open()) - MuStream.close(); + if (MuStream.is_open()) + MuStream.close(); - MuLogInitialized = false; + MuLogInitialized = false; } void -Mu::log_set_options (Mu::LogOptions opts) +Mu::log_set_options(Mu::LogOptions opts) { - MuLogOptions = opts; + MuLogOptions = opts; } Mu::LogOptions -Mu::log_get_options () +Mu::log_get_options() { - return MuLogOptions; + return MuLogOptions; } diff --git a/lib/utils/mu-logger.hh b/lib/utils/mu-logger.hh index ffd48b9e..15e983f2 100644 --- a/lib/utils/mu-logger.hh +++ b/lib/utils/mu-logger.hh @@ -30,9 +30,9 @@ namespace Mu { * */ enum struct LogOptions { - None = 0, /**< Nothing specific */ - StdOutErr = 1 << 1, /**< Log to stdout/stderr */ - Debug = 1 << 2, /**< Include debug-level logs */ + None = 0, /**< Nothing specific */ + StdOutErr = 1 << 1, /**< Log to stdout/stderr */ + Debug = 1 << 2, /**< Include debug-level logs */ }; /** @@ -43,7 +43,7 @@ enum struct LogOptions { * @param path path to the log file * @param opts logging options */ -void log_init (const std::string& path, LogOptions opts); +void log_init(const std::string& path, LogOptions opts); /** * Uninitialize the logging system @@ -56,15 +56,14 @@ void log_uninit(); * * @param opts options */ -void log_set_options (LogOptions opts); +void log_set_options(LogOptions opts); /** * Get the current log options * * @return the log options */ -LogOptions log_get_options (); - +LogOptions log_get_options(); } // namespace Mu MU_ENABLE_BITOPS(Mu::LogOptions); diff --git a/lib/utils/mu-option.hh b/lib/utils/mu-option.hh index cc042e8d..fb4a64a9 100644 --- a/lib/utils/mu-option.hh +++ b/lib/utils/mu-option.hh @@ -16,14 +16,18 @@ #include "optional.hpp" - namespace Mu { /// Either a value of type T, or None -template using Option=tl::optional; +template using Option = tl::optional; -template Option Some(T&& t) { return t; } +template +Option +Some(T&& t) +{ + return std::move(t); +} constexpr auto Nothing = tl::nullopt; // 'None' is take already -} +} // namespace Mu #endif /*MU_OPTION__*/ diff --git a/lib/utils/mu-readline.cc b/lib/utils/mu-readline.cc index 2fcd2245..0858cf1c 100644 --- a/lib/utils/mu-readline.cc +++ b/lib/utils/mu-readline.cc @@ -27,32 +27,31 @@ #include #ifdef HAVE_LIBREADLINE -# if defined(HAVE_READLINE_READLINE_H) -# include -# elif defined(HAVE_READLINE_H) -# include -# else /* !defined(HAVE_READLINE_H) */ -extern char *readline (); -# endif /* !defined(HAVE_READLINE_H) */ -char *cmdline = NULL; -#else /* !defined(HAVE_READLINE_READLINE_H) */ +#if defined(HAVE_READLINE_READLINE_H) +#include +#elif defined(HAVE_READLINE_H) +#include +#else /* !defined(HAVE_READLINE_H) */ +extern char* readline(); +#endif /* !defined(HAVE_READLINE_H) */ +char* cmdline = NULL; +#else /* !defined(HAVE_READLINE_READLINE_H) */ /* no readline */ #endif /* HAVE_LIBREADLINE */ #ifdef HAVE_READLINE_HISTORY -# if defined(HAVE_READLINE_HISTORY_H) -# include -# elif defined(HAVE_HISTORY_H) -# include -# else /* !defined(HAVE_HISTORY_H) */ -extern void add_history (); -extern int write_history (); -extern int read_history (); -# endif /* defined(HAVE_READLINE_HISTORY_H) */ +#if defined(HAVE_READLINE_HISTORY_H) +#include +#elif defined(HAVE_HISTORY_H) +#include +#else /* !defined(HAVE_HISTORY_H) */ +extern void add_history(); +extern int write_history(); +extern int read_history(); +#endif /* defined(HAVE_READLINE_HISTORY_H) */ /* no history */ #endif /* HAVE_READLINE_HISTORY */ - #if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY) #define HAVE_READLINE (1) #else @@ -66,66 +65,64 @@ static std::string hist_path; static size_t max_lines{}; void -Mu::setup_readline (const std::string& histpath, size_t maxlines) +Mu::setup_readline(const std::string& histpath, size_t maxlines) { - is_a_tty = !!::isatty(::fileno(stdout)); - hist_path = histpath; - max_lines = maxlines; + is_a_tty = !!::isatty(::fileno(stdout)); + hist_path = histpath; + max_lines = maxlines; #if HAVE_READLINE - rl_bind_key('\t', rl_insert); // default (filenames) is not useful - using_history(); - read_history(hist_path.c_str()); + rl_bind_key('\t', rl_insert); // default (filenames) is not useful + using_history(); + read_history(hist_path.c_str()); - if (max_lines > 0) - stifle_history(max_lines); + if (max_lines > 0) + stifle_history(max_lines); #endif /*HAVE_READLINE*/ } - void -Mu::shutdown_readline () +Mu::shutdown_readline() { #if HAVE_READLINE - if (!is_a_tty) - return; + if (!is_a_tty) + return; - write_history(hist_path.c_str()); - if (max_lines > 0) - history_truncate_file (hist_path.c_str(), max_lines); + write_history(hist_path.c_str()); + if (max_lines > 0) + history_truncate_file(hist_path.c_str(), max_lines); #endif /*HAVE_READLINE*/ } - std::string Mu::read_line(bool& do_quit) { #if HAVE_READLINE - if (is_a_tty) { - auto buf = readline(";; mu% "); - if (!buf) { - do_quit = true; - return {}; - } - std::string line{buf}; - ::free(buf); - return line; - } + if (is_a_tty) { + auto buf = readline(";; mu% "); + if (!buf) { + do_quit = true; + return {}; + } + std::string line{buf}; + ::free(buf); + return line; + } #endif /*HAVE_READLINE*/ - std::string line; - std::cout << ";; mu> "; - if (!std::getline(std::cin, line)) - do_quit = true; + std::string line; + std::cout << ";; mu> "; + if (!std::getline(std::cin, line)) + do_quit = true; - return line; + return line; } - void -Mu::save_line(const std::string& line) { +Mu::save_line(const std::string& line) +{ #if HAVE_READLINE - if (is_a_tty) - add_history(line.c_str()); + if (is_a_tty) + add_history(line.c_str()); #endif /*HAVE_READLINE*/ } diff --git a/lib/utils/mu-readline.hh b/lib/utils/mu-readline.hh index c30f84ae..feb0a15b 100644 --- a/lib/utils/mu-readline.hh +++ b/lib/utils/mu-readline.hh @@ -26,15 +26,14 @@ namespace Mu { * @param histpath path to the history file * @param max_lines maximum number of history to save */ -void setup_readline(const std::string &histpath, size_t max_lines); +void setup_readline(const std::string& histpath, size_t max_lines); /** * Shutdown readline -* + * */ void shutdown_readline(); - /** * Read a command line * @@ -42,13 +41,13 @@ void shutdown_readline(); * * @return the string read or empty */ -std::string read_line(bool &do_quit); +std::string read_line(bool& do_quit); /** * Save a line to history (or do nothing when readline is not active) * * @param line a line. */ -void save_line(const std::string &line); +void save_line(const std::string& line); } // namespace Mu diff --git a/lib/utils/mu-result.hh b/lib/utils/mu-result.hh index 3b1e1538..290ccfb5 100644 --- a/lib/utils/mu-result.hh +++ b/lib/utils/mu-result.hh @@ -17,32 +17,32 @@ ** */ - #ifndef MU_RESULT_HH__ #define MU_RESULT_HH__ - #include "expected.hpp" #include "utils/mu-error.hh" - namespace Mu { /** * A Result is _either_ some value of type T, _or_ an error. */ template using Result = tl::expected; -template typename Result::expected_type -Ok(T&& t) { - return Result::expected(std::move(t)); +template +typename Result::expected_type +Ok(T&& t) +{ + return Result::expected(std::move(t)); } -template typename Result::unexpected_type -Err(Error&& err) { - return Result::unexpected(std::move(err)); +template +typename Result::unexpected_type +Err(Error&& err) +{ + return Result::unexpected(std::move(err)); } } // namespace Mu - #endif /* MU_ERROR_HH__ */ diff --git a/lib/utils/mu-sexp.cc b/lib/utils/mu-sexp.cc index c48d83e6..0ca1f522 100644 --- a/lib/utils/mu-sexp.cc +++ b/lib/utils/mu-sexp.cc @@ -18,7 +18,6 @@ ** */ - #include "mu-sexp.hh" #include "mu-utils.hh" @@ -30,231 +29,221 @@ using namespace Mu; __attribute__((format(printf, 2, 0))) static Mu::Error parsing_error(size_t pos, const char* frm, ...) { - va_list args; - va_start(args, frm); - auto msg = vformat(frm, args); - va_end(args); + va_list args; + va_start(args, frm); + auto msg = vformat(frm, args); + va_end(args); - if (pos == 0) - return Mu::Error(Error::Code::Parsing, "%s", msg.c_str()); - else - return Mu::Error(Error::Code::Parsing, "%zu: %s", pos, msg.c_str()); + if (pos == 0) + return Mu::Error(Error::Code::Parsing, "%s", msg.c_str()); + else + return Mu::Error(Error::Code::Parsing, "%zu: %s", pos, msg.c_str()); } static size_t -skip_whitespace (const std::string& s, size_t pos) +skip_whitespace(const std::string& s, size_t pos) { - while (pos != s.size()) { - if (s[pos] == ' ' || s[pos] == '\t' || s[pos] == '\n') - ++pos; - else - break; - } + while (pos != s.size()) { + if (s[pos] == ' ' || s[pos] == '\t' || s[pos] == '\n') + ++pos; + else + break; + } - return pos; + return pos; } -static Sexp parse (const std::string& expr, size_t& pos); +static Sexp parse(const std::string& expr, size_t& pos); static Sexp -parse_list (const std::string& expr, size_t& pos) +parse_list(const std::string& expr, size_t& pos) { - if (expr[pos] != '(') // sanity check. - throw parsing_error(pos, "expected: '(' but got '%c", expr[pos]); + if (expr[pos] != '(') // sanity check. + throw parsing_error(pos, "expected: '(' but got '%c", expr[pos]); - Sexp::List list; + Sexp::List list; - ++pos; - while (expr[pos] != ')' && pos != expr.size()) - list.add(parse(expr, pos)); + ++pos; + while (expr[pos] != ')' && pos != expr.size()) + list.add(parse(expr, pos)); - if (expr[pos] != ')') - throw parsing_error(pos, "expected: ')' but got '%c'", expr[pos]); - ++pos; - return Sexp::make_list(std::move(list)); + if (expr[pos] != ')') + throw parsing_error(pos, "expected: ')' but got '%c'", expr[pos]); + ++pos; + return Sexp::make_list(std::move(list)); } // parse string static Sexp -parse_string (const std::string& expr, size_t& pos) +parse_string(const std::string& expr, size_t& pos) { - if (expr[pos] != '"') // sanity check. - throw parsing_error(pos, "expected: '\"'' but got '%c", expr[pos]); + if (expr[pos] != '"') // sanity check. + throw parsing_error(pos, "expected: '\"'' but got '%c", expr[pos]); - bool escape{}; - std::string str; - for (++pos; pos != expr.size(); ++pos) { + bool escape{}; + std::string str; + for (++pos; pos != expr.size(); ++pos) { + auto kar = expr[pos]; + if (escape && (kar == '"' || kar == '\\')) { + str += kar; + escape = false; + continue; + } - auto kar = expr[pos]; - if (escape && (kar == '"' || kar == '\\')) { - str += kar; - escape = false; - continue; - } + if (kar == '"') + break; + else if (kar == '\\') + escape = true; + else + str += kar; + } - if (kar == '"') - break; - else if (kar == '\\') - escape = true; - else - str += kar; - } + if (escape || expr[pos] != '"') + throw parsing_error(pos, "unterminated string '%s'", str.c_str()); - if (escape || expr[pos] != '"') - throw parsing_error(pos, "unterminated string '%s'", str.c_str()); - - ++pos; - return Sexp::make_string(std::move(str)); + ++pos; + return Sexp::make_string(std::move(str)); } static Sexp -parse_integer (const std::string& expr, size_t& pos) +parse_integer(const std::string& expr, size_t& pos) { - if (!isdigit(expr[pos]) && expr[pos] != '-') // sanity check. - throw parsing_error(pos, "expected: but got '%c", expr[pos]); + if (!isdigit(expr[pos]) && expr[pos] != '-') // sanity check. + throw parsing_error(pos, "expected: but got '%c", expr[pos]); - std::string num; // negative number? - if (expr[pos] == '-') { - num = "-"; - ++pos; - } + std::string num; // negative number? + if (expr[pos] == '-') { + num = "-"; + ++pos; + } - for (; isdigit(expr[pos]); ++pos) - num += expr[pos]; + for (; isdigit(expr[pos]); ++pos) + num += expr[pos]; - return Sexp::make_number(::atoi(num.c_str())); + return Sexp::make_number(::atoi(num.c_str())); } static Sexp -parse_symbol (const std::string& expr, size_t& pos) +parse_symbol(const std::string& expr, size_t& pos) { - if (!isalpha(expr[pos]) && expr[pos] != ':') // sanity check. - throw parsing_error(pos, "expected: |: but got '%c", expr[pos]); + if (!isalpha(expr[pos]) && expr[pos] != ':') // sanity check. + throw parsing_error(pos, "expected: |: but got '%c", expr[pos]); - std::string symbol(1, expr[pos]); - for (++pos; isalnum(expr[pos]) || expr[pos] == '-'; ++pos) - symbol += expr[pos]; + std::string symbol(1, expr[pos]); + for (++pos; isalnum(expr[pos]) || expr[pos] == '-'; ++pos) + symbol += expr[pos]; - return Sexp::make_symbol(std::move(symbol)); + return Sexp::make_symbol(std::move(symbol)); } - static Sexp -parse (const std::string& expr, size_t& pos) +parse(const std::string& expr, size_t& pos) { - pos = skip_whitespace(expr, pos); + pos = skip_whitespace(expr, pos); - if (pos == expr.size()) - throw parsing_error(pos, "expected: character '%c", expr[pos]); + if (pos == expr.size()) + throw parsing_error(pos, "expected: character '%c", expr[pos]); - const auto kar = expr[pos]; - const auto node =[&]() -> Sexp { - if (kar == '(') - return parse_list (expr, pos); - else if (kar == '"') - return parse_string(expr, pos); - else if (isdigit(kar) || kar == '-') - return parse_integer(expr, pos); - else if (isalpha(kar) || kar == ':') - return parse_symbol(expr, pos); - else - throw parsing_error(pos, "unexpected character '%c", kar); - }(); + const auto kar = expr[pos]; + const auto node = [&]() -> Sexp { + if (kar == '(') + return parse_list(expr, pos); + else if (kar == '"') + return parse_string(expr, pos); + else if (isdigit(kar) || kar == '-') + return parse_integer(expr, pos); + else if (isalpha(kar) || kar == ':') + return parse_symbol(expr, pos); + else + throw parsing_error(pos, "unexpected character '%c", kar); + }(); - pos = skip_whitespace(expr, pos); + pos = skip_whitespace(expr, pos); - return node; + return node; } Sexp -Sexp::make_parse (const std::string& expr) +Sexp::make_parse(const std::string& expr) { - size_t pos{}; - auto node{::parse (expr, pos)}; + size_t pos{}; + auto node{::parse(expr, pos)}; - if (pos != expr.size()) - throw parsing_error(pos, "trailing data starting with '%c'", expr[pos]); + if (pos != expr.size()) + throw parsing_error(pos, "trailing data starting with '%c'", expr[pos]); - return node; + return node; } - std::string -Sexp::to_sexp_string () const +Sexp::to_sexp_string() const { - std::stringstream sstrm; + std::stringstream sstrm; - switch (type()) { - case Type::List: { - sstrm << '('; - bool first{true}; - for (auto&& child : list()) { - sstrm << (first ? "" : " ") << child.to_sexp_string(); - first = false; - } - sstrm << ')'; - break; - } - case Type::String: - sstrm << quote(value()); - break; - case Type::Number: - case Type::Symbol: - case Type::Empty: - default: - sstrm << value(); - } + switch (type()) { + case Type::List: { + sstrm << '('; + bool first{true}; + for (auto&& child : list()) { + sstrm << (first ? "" : " ") << child.to_sexp_string(); + first = false; + } + sstrm << ')'; + break; + } + case Type::String: sstrm << quote(value()); break; + case Type::Number: + case Type::Symbol: + case Type::Empty: + default: sstrm << value(); + } - return sstrm.str(); + return sstrm.str(); } - std::string -Sexp::to_json_string () const +Sexp::to_json_string() const { - std::stringstream sstrm; + std::stringstream sstrm; - switch (type()) { - case Type::List: { - // property-lists become JSON objects - if (is_prop_list()) { - sstrm << "{"; - auto it{list().begin()}; - bool first{true}; - while (it != list().end()) { - sstrm << (first?"":",") << quote(it->value()) << ":"; - ++it; - sstrm << it->to_json_string(); - ++it; - first = false; - } - sstrm << "}"; - } else { // other lists become arrays. - sstrm << '['; - bool first{true}; - for (auto&& child : list()) { - sstrm << (first ? "" : ", ") << child.to_json_string(); - first = false; - } - sstrm << ']'; - } - break; - } - case Type::String: - sstrm << quote(value()); - break; - case Type::Symbol: - if (is_nil()) - sstrm << "false"; - else if (is_t()) - sstrm << "true"; - else - sstrm << quote(value()); - break; - case Type::Number: - case Type::Empty: - default: - sstrm << value(); - } + switch (type()) { + case Type::List: { + // property-lists become JSON objects + if (is_prop_list()) { + sstrm << "{"; + auto it{list().begin()}; + bool first{true}; + while (it != list().end()) { + sstrm << (first ? "" : ",") << quote(it->value()) << ":"; + ++it; + sstrm << it->to_json_string(); + ++it; + first = false; + } + sstrm << "}"; + } else { // other lists become arrays. + sstrm << '['; + bool first{true}; + for (auto&& child : list()) { + sstrm << (first ? "" : ", ") << child.to_json_string(); + first = false; + } + sstrm << ']'; + } + break; + } + case Type::String: sstrm << quote(value()); break; + case Type::Symbol: + if (is_nil()) + sstrm << "false"; + else if (is_t()) + sstrm << "true"; + else + sstrm << quote(value()); + break; + case Type::Number: + case Type::Empty: + default: sstrm << value(); + } - return sstrm.str(); + return sstrm.str(); } diff --git a/lib/utils/mu-sexp.hh b/lib/utils/mu-sexp.hh index 43cf1f47..bc4916a9 100644 --- a/lib/utils/mu-sexp.hh +++ b/lib/utils/mu-sexp.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_SEXP_HH__ #define MU_SEXP_HH__ @@ -35,331 +34,344 @@ namespace Mu { /// /// (:foo (1234 "bar" nil) :quux (a b c)) - /// Parse node struct Sexp { - /// Node type - enum struct Type { Empty, List, String, Number, Symbol }; + /// Node type + enum struct Type { Empty, List, String, Number, Symbol }; + /** + * Default CTOR + */ + Sexp() : type_{Type::Empty} {} - /** - * Default CTOR - */ - Sexp():type_{Type::Empty}{} + // Underlying data type for list; we'd like to use std::dequeu here, + // but that does not compile with libc++ (it does with libstdc++) + using Seq = std::vector; - // Underlying data type for list; we'd like to use std::dequeu here, - // but that does not compile with libc++ (it does with libstdc++) - using Seq = std::vector; + /** + * Make a sexp out of an s-expression string. + * + * @param expr a string containing an s-expression + * + * @return the parsed s-expression, or throw Error. + */ + static Sexp make_parse(const std::string& expr); - /** - * Make a sexp out of an s-expression string. - * - * @param expr a string containing an s-expression - * - * @return the parsed s-expression, or throw Error. - */ - static Sexp make_parse (const std::string& expr); + /** + * Make a node for a string/integer/symbol/list value + * + * @param val some value + * + * @return a node + */ + static Sexp make_string(std::string&& val) { return Sexp{Type::String, std::move(val)}; } + static Sexp make_string(const std::string& val) + { + return Sexp{Type::String, std::string(val)}; + } + static Sexp make_number(int val) { return Sexp{Type::Number, format("%d", val)}; } + static Sexp make_symbol(std::string&& val) + { + if (val.empty()) + throw Error(Error::Code::InvalidArgument, "symbol must be non-empty"); + return Sexp{Type::Symbol, std::move(val)}; + } - /** - * Make a node for a string/integer/symbol/list value - * - * @param val some value - * - * @return a node - */ - static Sexp make_string (std::string&& val) { return Sexp{Type::String, std::move(val)}; } - static Sexp make_string (const std::string& val) { return Sexp{Type::String, std::string(val)}; } - static Sexp make_number (int val) { return Sexp{Type::Number, format("%d", val)}; } - static Sexp make_symbol (std::string&& val) { - if (val.empty()) - throw Error(Error::Code::InvalidArgument, "symbol must be non-empty"); - return Sexp{Type::Symbol, std::move(val)}; - } + /** + * + * + * The value of this node; invalid for list nodes. + * + * @return + */ + const std::string& value() const + { + if (is_list()) + throw Error(Error::Code::InvalidArgument, "no value for list"); + if (is_empty()) + throw Error{Error::Code::InvalidArgument, "no value for empty"}; + return value_; + } - /** - * - * - * The value of this node; invalid for list nodes. - * - * @return - */ - const std::string& value() const { - if (is_list()) - throw Error(Error::Code::InvalidArgument, "no value for list"); - if (is_empty()) - throw Error{Error::Code::InvalidArgument, "no value for empty"}; - return value_; - } + /** + * The underlying container of this list node; only valid for lists + * + * @return + */ + const Seq& list() const + { + if (!is_list()) + throw Error(Error::Code::InvalidArgument, "not a list"); + return seq_; + } - /** - * The underlying container of this list node; only valid for lists - * - * @return - */ - const Seq& list() const { - if (!is_list()) - throw Error(Error::Code::InvalidArgument, "not a list"); - return seq_; - } + /** + * Convert a Sexp::Node to its S-expression string representation + * + * @return the string representation + */ + std::string to_sexp_string() const; - /** - * Convert a Sexp::Node to its S-expression string representation - * - * @return the string representation - */ - std::string to_sexp_string() const; + /** + * Convert a Sexp::Node to its JSON string representation + * + * @return the string representation + */ + std::string to_json_string() const; + /** + * Return the type of this Node. + * + * @return the type + */ + Type type() const { return type_; } - /** - * Convert a Sexp::Node to its JSON string representation - * - * @return the string representation - */ - std::string to_json_string() const; + /// + /// Helper struct to build mutable lists. + /// + struct List { + /** + * Add a sexp to the list + * + * @param sexp a sexp + * @param args rest arguments + * + * @return a ref to this List (for chaining) + */ + List& add() { return *this; } + List& add(Sexp&& sexp) + { + seq_.emplace_back(std::move(sexp)); + return *this; + } + template List& add(Sexp&& sexp, Args... args) + { + seq_.emplace_back(std::move(sexp)); + seq_.emplace_back(std::forward(args)...); + return *this; + } - /** - * Return the type of this Node. - * - * @return the type - */ - Type type() const { return type_; } + /** + * Add a property (i.e., :key sexp ) to the list + * + * @param name a property-name. Must start with ':', length > 1 + * @param sexp a sexp + * @param args rest arguments + * + * @return a ref to this List (for chaining) + */ + List& add_prop(std::string&& name, Sexp&& sexp) + { + if (!is_prop_name(name)) + throw Error{Error::Code::InvalidArgument, + "invalid property name ('%s')", + name.c_str()}; + seq_.emplace_back(make_symbol(std::move(name))); + seq_.emplace_back(std::move(sexp)); + return *this; + } + template + List& add_prop(std::string&& name, Sexp&& sexp, Args... args) + { + add_prop(std::move(name), std::move(sexp)); + add_prop(std::forward(args)...); + return *this; + } - /// - /// Helper struct to build mutable lists. - /// - struct List { - /** - * Add a sexp to the list - * - * @param sexp a sexp - * @param args rest arguments - * - * @return a ref to this List (for chaining) - */ - List& add () { return *this; } - List& add (Sexp&& sexp) { seq_.emplace_back(std::move(sexp)); return *this; } - template List& add (Sexp&& sexp, Args... args) { - seq_.emplace_back(std::move(sexp)); - seq_.emplace_back(std::forward(args)...); - return *this; - } + /** + * Get the number of elements in the list + * + * @return number + */ + size_t size() const { return seq_.size(); } - /** - * Add a property (i.e., :key sexp ) to the list - * - * @param name a property-name. Must start with ':', length > 1 - * @param sexp a sexp - * @param args rest arguments - * - * @return a ref to this List (for chaining) - */ - List& add_prop (std::string&& name, Sexp&& sexp) { - if (!is_prop_name(name)) - throw Error{Error::Code::InvalidArgument, "invalid property name ('%s')", - name.c_str()}; - seq_.emplace_back(make_symbol(std::move(name))); - seq_.emplace_back(std::move(sexp)); - return *this; - } - template - List& add_prop (std::string&& name, Sexp&& sexp, Args... args) { - add_prop(std::move(name), std::move(sexp)); - add_prop(std::forward(args)...); - return *this; - } + /** + * Is the list empty? + * + * @return true or false + */ + size_t empty() const { return seq_.empty(); } - /** - * Get the number of elements in the list - * - * @return number - */ - size_t size() const { return seq_.size(); } + private: + friend struct Sexp; + Seq seq_; + }; - /** - * Is the list empty? - * - * @return true or false - */ - size_t empty() const { return seq_.empty(); } + /** + * Construct a list sexp from a List + * + * @param list a list-list + * @param sexp a Sexp + * @param args rest arguments + * + * @return a sexp. + */ + static Sexp make_list(List&& list) { return Sexp{Type::List, std::move(list.seq_)}; } + template static Sexp make_list(Sexp&& sexp, Args... args) + { + List lst; + lst.add(std::move(sexp)).add(std::forward(args)...); + return make_list(std::move(lst)); + } - private: - friend struct Sexp; - Seq seq_; - }; + /** + * Construct a property list sexp from a List + * + * @param name the property name; must start wtth ':' + * @param sexp a Sexp + * @param args rest arguments (property list) + * + * @return a sexp. + */ + template + static Sexp make_prop_list(std::string&& name, Sexp&& sexp, Args... args) + { + List list; + list.add_prop(std::move(name), std::move(sexp), std::forward(args)...); + return make_list(std::move(list)); + } - /** - * Construct a list sexp from a List - * - * @param list a list-list - * @param sexp a Sexp - * @param args rest arguments - * - * @return a sexp. - */ - static Sexp make_list(List&& list) { - return Sexp{Type::List, std::move(list.seq_)}; - } - template - static Sexp make_list(Sexp&& sexp, Args... args) { - List lst; - lst.add(std::move(sexp)).add(std::forward(args)...); - return make_list(std::move(lst)); - } + /** + * Construct a properrty list sexp from a List + * + * @param funcname function name for the call + * @param name the property name; must start wtth ':' + * @param sexp a Sexp + * @param args rest arguments (property list) + * + * @return a sexp. + */ + template + static Sexp make_call(std::string&& funcname, std::string&& name, Sexp&& sexp, Args... args) + { + List list; + list.add(make_symbol(std::move(funcname))); + list.add_prop(std::move(name), std::move(sexp), std::forward(args)...); + return make_list(std::move(list)); + } - /** - * Construct a property list sexp from a List - * - * @param name the property name; must start wtth ':' - * @param sexp a Sexp - * @param args rest arguments (property list) - * - * @return a sexp. - */ - template - static Sexp make_prop_list(std::string&& name, Sexp&& sexp, Args... args) { - List list; - list.add_prop(std::move(name), std::move(sexp), std::forward(args)...); - return make_list(std::move(list)); + /// Some type helpers + bool is_list() const { return type() == Type::List; } + bool is_string() const { return type() == Type::String; } + bool is_number() const { return type() == Type::Number; } + bool is_symbol() const { return type() == Type::Symbol; } + bool is_empty() const { return type() == Type::Empty; } - } + operator bool() const { return !is_empty(); } - /** - * Construct a properrty list sexp from a List - * - * @param funcname function name for the call - * @param name the property name; must start wtth ':' - * @param sexp a Sexp - * @param args rest arguments (property list) - * - * @return a sexp. - */ - template - static Sexp make_call(std::string&& funcname, std::string&& name, Sexp&& sexp, Args... args) { - List list; - list.add(make_symbol(std::move(funcname))); - list.add_prop(std::move(name), std::move(sexp), std::forward(args)...); - return make_list(std::move(list)); + static constexpr auto SymbolNil{"nil"}; + static constexpr auto SymbolT{"t"}; + bool is_nil() const { return is_symbol() && value() == SymbolNil; } + bool is_t() const { return is_symbol() && value() == SymbolT; } - } + /** + * Is this a prop-list? A prop list is a list sexp with alternating + * property / sexp + * + * @return + */ + bool is_prop_list() const + { + if (!is_list() || list().size() % 2 != 0) + return false; + else + return is_prop_list(list().begin(), list().end()); + } + /** + * Is this a call? A call is a list sexp with a symbol (function name), + * followed by a prop list + * + * @return + */ + bool is_call() const + { + if (!is_list() || list().size() % 2 != 1 || !list().at(0).is_symbol()) + return false; + else + return is_prop_list(list().begin() + 1, list().end()); + }; - /// Some type helpers - bool is_list() const { return type() == Type::List; } - bool is_string() const { return type() == Type::String; } - bool is_number() const { return type() == Type::Number; } - bool is_symbol() const { return type() == Type::Symbol; } - bool is_empty() const { return type() == Type::Empty; } + private: + Sexp(Type typearg, std::string&& valuearg) : type_{typearg}, value_{std::move(valuearg)} + { + if (is_list()) + throw Error{Error::Code::InvalidArgument, "cannot be a list type"}; + if (is_empty()) + throw Error{Error::Code::InvalidArgument, "cannot be an empty type"}; + } + Sexp(Type typearg, Seq&& seq) : type_{Type::List}, seq_{std::move(seq)} + { + if (!is_list()) + throw Error{Error::Code::InvalidArgument, "must be a list type"}; + if (is_empty()) + throw Error{Error::Code::InvalidArgument, "cannot be an empty type"}; + } + /** + * Is the sexp a valid property name? + * + * @param sexp a Sexp. + * + * @return true or false. + */ + static bool is_prop_name(const std::string& str) + { + return str.size() > 1 && str.at(0) == ':'; + } + static bool is_prop_name(const Sexp& sexp) + { + return sexp.is_symbol() && is_prop_name(sexp.value()); + } - operator bool() const { return !is_empty(); } + static bool is_prop_list(Seq::const_iterator b, Seq::const_iterator e) + { + while (b != e) { + const Sexp& s{*b}; + if (!is_prop_name(s)) + return false; + if (++b == e) + return false; + ++b; + } + return b == e; + } - static constexpr auto SymbolNil{"nil"}; - static constexpr auto SymbolT{"t"}; - bool is_nil() const { return is_symbol() && value() == SymbolNil; } - bool is_t() const { return is_symbol() && value() == SymbolT; } - - /** - * Is this a prop-list? A prop list is a list sexp with alternating - * property / sexp - * - * @return - */ - bool is_prop_list() const { - if (!is_list() || list().size() % 2 != 0) - return false; - else - return is_prop_list(list().begin(), list().end()); - } - - /** - * Is this a call? A call is a list sexp with a symbol (function name), - * followed by a prop list - * - * @return - */ - bool is_call() const { - if (!is_list() || list().size() % 2 != 1 || !list().at(0).is_symbol()) - return false; - else - return is_prop_list (list().begin()+1, list().end()); - }; - -private: - Sexp(Type typearg, std::string&& valuearg): type_{typearg}, value_{std::move(valuearg)} { - if (is_list()) - throw Error{Error::Code::InvalidArgument, "cannot be a list type"}; - if (is_empty()) - throw Error{Error::Code::InvalidArgument, "cannot be an empty type"}; - - } - Sexp(Type typearg, Seq&& seq): type_{Type::List}, seq_{std::move(seq)}{ - if (!is_list()) - throw Error{Error::Code::InvalidArgument, "must be a list type"}; - if (is_empty()) - throw Error{Error::Code::InvalidArgument, "cannot be an empty type"}; - } - /** - * Is the sexp a valid property name? - * - * @param sexp a Sexp. - * - * @return true or false. - */ - static bool is_prop_name(const std::string& str) { - return str.size() > 1 && str.at(0) == ':'; - } - static bool is_prop_name(const Sexp& sexp) { - return sexp.is_symbol() && is_prop_name(sexp.value()); - } - - static bool is_prop_list (Seq::const_iterator b, Seq::const_iterator e) { - while (b != e) { - const Sexp& s{*b}; - if (!is_prop_name(s)) - return false; - if (++b == e) - return false; - ++b; - } - return b == e; - } - - const Type type_; /**< Type of node */ - const std::string value_; /**< String value of node (only for - * non-Type::Lst)*/ - const Seq seq_; /**< Children of node (only for - * Type::Lst) */ + const Type type_; /**< Type of node */ + const std::string value_; /**< String value of node (only for + * non-Type::Lst)*/ + const Seq seq_; /**< Children of node (only for + * Type::Lst) */ }; static inline std::ostream& operator<<(std::ostream& os, Sexp::Type id) { - switch (id) { - case Sexp::Type::List: os << "list"; break; - case Sexp::Type::String: os << "string"; break; - case Sexp::Type::Number: os << "number"; break; - case Sexp::Type::Symbol: os << "symbol"; break; - case Sexp::Type::Empty: os << "empty"; break; - default: throw std::runtime_error ("unknown node type"); - } + switch (id) { + case Sexp::Type::List: os << "list"; break; + case Sexp::Type::String: os << "string"; break; + case Sexp::Type::Number: os << "number"; break; + case Sexp::Type::Symbol: os << "symbol"; break; + case Sexp::Type::Empty: os << "empty"; break; + default: throw std::runtime_error("unknown node type"); + } - return os; + return os; } static inline std::ostream& operator<<(std::ostream& os, const Sexp& sexp) { - os << sexp.to_sexp_string(); - return os; + os << sexp.to_sexp_string(); + return os; } static inline std::ostream& operator<<(std::ostream& os, const Sexp::List& sexp) { - os << Sexp::make_list(Sexp::List(sexp)); - return os; + os << Sexp::make_list(Sexp::List(sexp)); + return os; } - -} // Mu +} // namespace Mu #endif /* MU_SEXP_HH__ */ diff --git a/lib/utils/mu-utils.cc b/lib/utils/mu-utils.cc index 619d4849..a8e12235 100644 --- a/lib/utils/mu-utils.cc +++ b/lib/utils/mu-utils.cc @@ -17,7 +17,6 @@ ** 02110-1301, USA. */ - #define _XOPEN_SOURCE #include @@ -40,24 +39,24 @@ using namespace Mu; namespace { static gunichar -unichar_tolower (gunichar uc) +unichar_tolower(gunichar uc) { - if (!g_unichar_isalpha(uc)) - return uc; + if (!g_unichar_isalpha(uc)) + return uc; - if (g_unichar_get_script (uc) != G_UNICODE_SCRIPT_LATIN) - return g_unichar_tolower (uc); + if (g_unichar_get_script(uc) != G_UNICODE_SCRIPT_LATIN) + return g_unichar_tolower(uc); - switch (uc) - { - case 0x00e6: - case 0x00c6: return 'e'; /* æ */ - case 0x00f8: return 'o'; /* ø */ - case 0x0110: - case 0x0111: return 'd'; /* đ */ - /* todo: many more */ - default: return g_unichar_tolower (uc); - } + switch (uc) { + case 0x00e6: + case 0x00c6: return 'e'; /* æ */ + case 0x00f8: return 'o'; /* ø */ + case 0x0110: + case 0x0111: + return 'd'; /* đ */ + /* todo: many more */ + default: return g_unichar_tolower(uc); + } } /** @@ -70,338 +69,328 @@ unichar_tolower (gunichar uc) * Returns: (transfer full): a flattened string, free with g_free(). */ static char* -gx_utf8_flatten (const gchar *str, gssize len) +gx_utf8_flatten(const gchar* str, gssize len) { - GString *gstr; - char *norm, *cur; + GString* gstr; + char * norm, *cur; - g_return_val_if_fail (str, NULL); + g_return_val_if_fail(str, NULL); - norm = g_utf8_normalize (str, len, G_NORMALIZE_ALL); - if (!norm) - return NULL; + norm = g_utf8_normalize(str, len, G_NORMALIZE_ALL); + if (!norm) + return NULL; - gstr = g_string_sized_new (strlen (norm)); + gstr = g_string_sized_new(strlen(norm)); - for (cur = norm; cur && *cur; cur = g_utf8_next_char (cur)) - { - gunichar uc; + for (cur = norm; cur && *cur; cur = g_utf8_next_char(cur)) { + gunichar uc; - uc = g_utf8_get_char (cur); - if (g_unichar_combining_class (uc) != 0) - continue; + uc = g_utf8_get_char(cur); + if (g_unichar_combining_class(uc) != 0) + continue; - g_string_append_unichar (gstr, unichar_tolower(uc)); - } + g_string_append_unichar(gstr, unichar_tolower(uc)); + } - g_free (norm); + g_free(norm); - return g_string_free (gstr, FALSE); + return g_string_free(gstr, FALSE); } } // namespace std::string // gx_utf8_flatten -Mu::utf8_flatten (const char *str) +Mu::utf8_flatten(const char* str) { - if (!str) - return {}; + if (!str) + return {}; - // the pure-ascii case - if (g_str_is_ascii(str)) { - auto l = g_ascii_strdown (str, -1); - std::string s{l}; - g_free (l); - return s; - } + // the pure-ascii case + if (g_str_is_ascii(str)) { + auto l = g_ascii_strdown(str, -1); + std::string s{l}; + g_free(l); + return s; + } - // seems we need the big guns - char *flat = gx_utf8_flatten (str, -1); - if (!flat) - return {}; + // seems we need the big guns + char* flat = gx_utf8_flatten(str, -1); + if (!flat) + return {}; - std::string s{flat}; - g_free (flat); + std::string s{flat}; + g_free(flat); - return s; + return s; } std::string -Mu::utf8_clean (const std::string& dirty) +Mu::utf8_clean(const std::string& dirty) { - GString *gstr = g_string_sized_new (dirty.length()); + GString* gstr = g_string_sized_new(dirty.length()); - for (auto cur = dirty.c_str(); cur && *cur; cur = g_utf8_next_char (cur)) { + for (auto cur = dirty.c_str(); cur && *cur; cur = g_utf8_next_char(cur)) { + const gunichar uc = g_utf8_get_char(cur); + if (g_unichar_iscntrl(uc)) + g_string_append_c(gstr, ' '); + else + g_string_append_unichar(gstr, uc); + } - const gunichar uc = g_utf8_get_char (cur); - if (g_unichar_iscntrl (uc)) - g_string_append_c (gstr, ' '); - else - g_string_append_unichar (gstr, uc); - } + std::string clean(gstr->str, gstr->len); + g_string_free(gstr, TRUE); - std::string clean(gstr->str, gstr->len); - g_string_free (gstr, TRUE); + clean.erase(0, clean.find_first_not_of(" ")); + clean.erase(clean.find_last_not_of(" ") + 1); // remove trailing space - clean.erase (0, clean.find_first_not_of(" ")); - clean.erase (clean.find_last_not_of(" ") + 1); // remove trailing space - - return clean; + return clean; } - std::string -Mu::remove_ctrl (const std::string& str) +Mu::remove_ctrl(const std::string& str) { - char prev{'\0'}; - std::string result; - result.reserve(str.length()); + char prev{'\0'}; + std::string result; + result.reserve(str.length()); - for (auto&& c: str) { - if (::iscntrl(c) || c == ' ') { - if (prev != ' ') - result += prev = ' '; - } else - result += prev = c; - } + for (auto&& c : str) { + if (::iscntrl(c) || c == ' ') { + if (prev != ' ') + result += prev = ' '; + } else + result += prev = c; + } - return result; + return result; } - std::vector -Mu::split (const std::string& str, const std::string& sepa) +Mu::split(const std::string& str, const std::string& sepa) { - char **parts = g_strsplit(str.c_str(), sepa.c_str(), -1); - std::vector vec; - for (auto part = parts; part && *part; ++part) - vec.push_back (*part); + char** parts = g_strsplit(str.c_str(), sepa.c_str(), -1); + std::vector vec; + for (auto part = parts; part && *part; ++part) + vec.push_back(*part); - g_strfreev(parts); + g_strfreev(parts); - return vec; + return vec; } std::string -Mu::quote (const std::string& str) +Mu::quote(const std::string& str) { - std::string res{"\""}; + std::string res{"\""}; - for (auto&& k: str) { - switch (k) { - case '"' : res += "\\\""; break; - case '\\': res += "\\\\"; break; - default: res += k; - } - } + for (auto&& k : str) { + switch (k) { + case '"': res += "\\\""; break; + case '\\': res += "\\\\"; break; + default: res += k; + } + } - return res + "\""; + return res + "\""; } - std::string - Mu::format (const char *frm, ...) - { - va_list args; - - va_start (args, frm); - auto str = vformat(frm, args); - va_end (args); - - return str; - } - std::string -Mu::vformat (const char *frm, va_list args) +Mu::format(const char* frm, ...) { - char *s{}; - const auto res = g_vasprintf (&s, frm, args); - if (res == -1) { - std::cerr << "string format failed" << std::endl; - return {}; - } + va_list args; - std::string str{s}; - g_free (s); + va_start(args, frm); + auto str = vformat(frm, args); + va_end(args); - return str; + return str; } +std::string +Mu::vformat(const char* frm, va_list args) +{ + char* s{}; + const auto res = g_vasprintf(&s, frm, args); + if (res == -1) { + std::cerr << "string format failed" << std::endl; + return {}; + } + + std::string str{s}; + g_free(s); + + return str; +} constexpr const auto InternalDateFormat = "%010" G_GINT64_FORMAT; -constexpr const char InternalDateMin[] = "0000000000"; -constexpr const char InternalDateMax[] = "9999999999"; +constexpr const char InternalDateMin[] = "0000000000"; +constexpr const char InternalDateMax[] = "9999999999"; static_assert(sizeof(InternalDateMin) == 10 + 1, "invalid"); static_assert(sizeof(InternalDateMax) == 10 + 1, "invalid"); static std::string -date_boundary (bool is_first) +date_boundary(bool is_first) { - return is_first ? InternalDateMin : InternalDateMax; + return is_first ? InternalDateMin : InternalDateMax; } std::string -Mu::date_to_time_t_string (int64_t t) +Mu::date_to_time_t_string(int64_t t) { - char buf[sizeof(InternalDateMax)]; - g_snprintf (buf, sizeof(buf), InternalDateFormat, t); + char buf[sizeof(InternalDateMax)]; + g_snprintf(buf, sizeof(buf), InternalDateFormat, t); - return buf; + return buf; } static std::string -delta_ymwdhMs (const std::string& expr) +delta_ymwdhMs(const std::string& expr) { - char *endptr; - auto num = strtol (expr.c_str(), &endptr, 10); - if (num <= 0 || num > 9999 || !endptr || !*endptr) - return date_boundary (true); + char* endptr; + auto num = strtol(expr.c_str(), &endptr, 10); + if (num <= 0 || num > 9999 || !endptr || !*endptr) + return date_boundary(true); - int years, months, weeks, days, hours, minutes, seconds; - years = months = weeks = days = hours = minutes = seconds = 0; + int years, months, weeks, days, hours, minutes, seconds; + years = months = weeks = days = hours = minutes = seconds = 0; - switch (endptr[0]) { - case 's': seconds = num; break; - case 'M': minutes = num; break; - case 'h': hours = num; break; - case 'd': days = num; break; - case 'w': weeks = num; break; - case 'm': months = num; break; - case 'y': years = num; break; - default: - return date_boundary (true); - } + switch (endptr[0]) { + case 's': seconds = num; break; + case 'M': minutes = num; break; + case 'h': hours = num; break; + case 'd': days = num; break; + case 'w': weeks = num; break; + case 'm': months = num; break; + case 'y': years = num; break; + default: return date_boundary(true); + } - GDateTime *then, *now = g_date_time_new_now_local (); - if (weeks != 0) - then = g_date_time_add_weeks (now, -weeks); - else - then = g_date_time_add_full (now, -years, -months,-days, - -hours, -minutes, -seconds); + GDateTime *then, *now = g_date_time_new_now_local(); + if (weeks != 0) + then = g_date_time_add_weeks(now, -weeks); + else + then = + g_date_time_add_full(now, -years, -months, -days, -hours, -minutes, -seconds); - time_t t = MAX (0, (gint64)g_date_time_to_unix (then)); + time_t t = MAX(0, (gint64)g_date_time_to_unix(then)); - g_date_time_unref (then); - g_date_time_unref (now); + g_date_time_unref(then); + g_date_time_unref(now); - return date_to_time_t_string (t); + return date_to_time_t_string(t); } static std::string -special_date (const std::string& d, bool is_first) +special_date(const std::string& d, bool is_first) { - if (d == "now") - return date_to_time_t_string (time(NULL)); + if (d == "now") + return date_to_time_t_string(time(NULL)); - else if (d == "today") { + else if (d == "today") { + GDateTime *dt, *midnight; + dt = g_date_time_new_now_local(); - GDateTime *dt, *midnight; - dt = g_date_time_new_now_local (); + if (!is_first) { + GDateTime* tmp = dt; + dt = g_date_time_add_days(dt, 1); + g_date_time_unref(tmp); + } - if (!is_first) { - GDateTime *tmp = dt; - dt = g_date_time_add_days (dt, 1); - g_date_time_unref (tmp); - } + midnight = g_date_time_add_full(dt, + 0, + 0, + 0, + -g_date_time_get_hour(dt), + -g_date_time_get_minute(dt), + -g_date_time_get_second(dt)); + time_t t = MAX(0, (gint64)g_date_time_to_unix(midnight)); + g_date_time_unref(dt); + g_date_time_unref(midnight); + return date_to_time_t_string((time_t)t); - midnight = g_date_time_add_full (dt, 0, 0, 0, - -g_date_time_get_hour(dt), - -g_date_time_get_minute (dt), - -g_date_time_get_second (dt)); - time_t t = MAX(0, (gint64)g_date_time_to_unix (midnight)); - g_date_time_unref (dt); - g_date_time_unref (midnight); - return date_to_time_t_string ((time_t)t); - - } else - return date_boundary (is_first); + } else + return date_boundary(is_first); } // if a date has a month day greater than the number of days in that month, // change it to a valid date point to the last second in that month static void -fixup_month (struct tm *tbuf) +fixup_month(struct tm* tbuf) { - decltype(tbuf->tm_mday) max_days; - const auto month = tbuf->tm_mon + 1; - const auto year = tbuf->tm_year + 1900; + decltype(tbuf->tm_mday) max_days; + const auto month = tbuf->tm_mon + 1; + const auto year = tbuf->tm_year + 1900; - switch (month) { - case 2: - if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) - max_days = 29; - else - max_days = 28; - break; - case 4: - case 6: - case 9: - case 11: - max_days = 30; - break; - default: - max_days = 31; - break; - } + switch (month) { + case 2: + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + max_days = 29; + else + max_days = 28; + break; + case 4: + case 6: + case 9: + case 11: max_days = 30; break; + default: max_days = 31; break; + } - if (tbuf->tm_mday > max_days) { - tbuf->tm_mday = max_days; - tbuf->tm_hour = 23; - tbuf->tm_min = 59; - tbuf->tm_sec = 59; - } + if (tbuf->tm_mday > max_days) { + tbuf->tm_mday = max_days; + tbuf->tm_hour = 23; + tbuf->tm_min = 59; + tbuf->tm_sec = 59; + } } std::string -Mu::date_to_time_t_string (const std::string& dstr, bool is_first) +Mu::date_to_time_t_string(const std::string& dstr, bool is_first) { - gint64 t; - struct tm tbuf; - GDateTime *dtime; + gint64 t; + struct tm tbuf; + GDateTime* dtime; - /* one-sided dates */ - if (dstr.empty()) - return date_boundary (is_first); - else if (dstr == "today" || dstr == "now") - return special_date (dstr, is_first); + /* one-sided dates */ + if (dstr.empty()) + return date_boundary(is_first); + else if (dstr == "today" || dstr == "now") + return special_date(dstr, is_first); - else if (dstr.find_first_of("ymdwhMs") != std::string::npos) - return delta_ymwdhMs (dstr); + else if (dstr.find_first_of("ymdwhMs") != std::string::npos) + return delta_ymwdhMs(dstr); - constexpr char UserDateMin[] = "19700101000000"; - constexpr char UserDateMax[] = "29991231235959"; + constexpr char UserDateMin[] = "19700101000000"; + constexpr char UserDateMax[] = "29991231235959"; - std::string date (is_first ? UserDateMin : UserDateMax); - std::copy_if (dstr.begin(), dstr.end(), date.begin(),[](auto c){return isdigit(c);}); + std::string date(is_first ? UserDateMin : UserDateMax); + std::copy_if(dstr.begin(), dstr.end(), date.begin(), [](auto c) { return isdigit(c); }); - memset (&tbuf, 0, sizeof tbuf); - if (!strptime (date.c_str(), "%Y%m%d%H%M%S", &tbuf) && - !strptime (date.c_str(), "%Y%m%d%H%M", &tbuf) && - !strptime (date.c_str(), "%Y%m%d", &tbuf) && - !strptime (date.c_str(), "%Y%m", &tbuf) && - !strptime (date.c_str(), "%Y", &tbuf)) - return date_boundary (is_first); + memset(&tbuf, 0, sizeof tbuf); + if (!strptime(date.c_str(), "%Y%m%d%H%M%S", &tbuf) && + !strptime(date.c_str(), "%Y%m%d%H%M", &tbuf) && + !strptime(date.c_str(), "%Y%m%d", &tbuf) && !strptime(date.c_str(), "%Y%m", &tbuf) && + !strptime(date.c_str(), "%Y", &tbuf)) + return date_boundary(is_first); - fixup_month(&tbuf); + fixup_month(&tbuf); - dtime = g_date_time_new_local (tbuf.tm_year + 1900, - tbuf.tm_mon + 1, - tbuf.tm_mday, - tbuf.tm_hour, - tbuf.tm_min, - tbuf.tm_sec); - if (!dtime) { - g_warning ("invalid %s date '%s'", - is_first ? "lower" : "upper", date.c_str()); - return date_boundary (is_first); - } + dtime = g_date_time_new_local(tbuf.tm_year + 1900, + tbuf.tm_mon + 1, + tbuf.tm_mday, + tbuf.tm_hour, + tbuf.tm_min, + tbuf.tm_sec); + if (!dtime) { + g_warning("invalid %s date '%s'", is_first ? "lower" : "upper", date.c_str()); + return date_boundary(is_first); + } - t = g_date_time_to_unix (dtime); - g_date_time_unref (dtime); + t = g_date_time_to_unix(dtime); + g_date_time_unref(dtime); - if (t < 0 || t > 9999999999) - return date_boundary (is_first); - else - return date_to_time_t_string (t); + if (t < 0 || t > 9999999999) + return date_boundary(is_first); + else + return date_to_time_t_string(t); } constexpr const auto SizeFormat = "%010" G_GINT64_FORMAT; @@ -412,98 +401,91 @@ static_assert(sizeof(SizeMin) == 10 + 1, "invalid"); static_assert(sizeof(SizeMax) == 10 + 1, "invalid"); static std::string -size_boundary (bool is_first) +size_boundary(bool is_first) { - return is_first ? SizeMin : SizeMax; + return is_first ? SizeMin : SizeMax; } std::string -Mu::size_to_string (int64_t size) +Mu::size_to_string(int64_t size) { - char buf[sizeof(SizeMax)]; - g_snprintf (buf, sizeof(buf), SizeFormat, size); + char buf[sizeof(SizeMax)]; + g_snprintf(buf, sizeof(buf), SizeFormat, size); - return buf; + return buf; } std::string -Mu::size_to_string (const std::string& val, bool is_first) +Mu::size_to_string(const std::string& val, bool is_first) { - std::string str; - GRegex *rx; - GMatchInfo *minfo; + std::string str; + GRegex* rx; + GMatchInfo* minfo; - /* one-sided ranges */ - if (val.empty()) - return size_boundary (is_first); + /* one-sided ranges */ + if (val.empty()) + return size_boundary(is_first); - rx = g_regex_new ("(\\d+)(b|k|kb|m|mb|g|gb)?", - G_REGEX_CASELESS, (GRegexMatchFlags)0, NULL); - minfo = NULL; - if (g_regex_match (rx, val.c_str(), (GRegexMatchFlags)0, &minfo)) { - gint64 size; - char *s; + rx = g_regex_new("(\\d+)(b|k|kb|m|mb|g|gb)?", G_REGEX_CASELESS, (GRegexMatchFlags)0, NULL); + minfo = NULL; + if (g_regex_match(rx, val.c_str(), (GRegexMatchFlags)0, &minfo)) { + gint64 size; + char* s; - s = g_match_info_fetch (minfo, 1); - size = atoll (s); - g_free (s); + s = g_match_info_fetch(minfo, 1); + size = atoll(s); + g_free(s); - s = g_match_info_fetch (minfo, 2); - switch (s ? g_ascii_tolower(s[0]) : 0) { - case 'k': size *= 1024; break; - case 'm': size *= (1024 * 1024); break; - case 'g': size *= (1024 * 1024 * 1024); break; - default: break; - } + s = g_match_info_fetch(minfo, 2); + switch (s ? g_ascii_tolower(s[0]) : 0) { + case 'k': size *= 1024; break; + case 'm': size *= (1024 * 1024); break; + case 'g': size *= (1024 * 1024 * 1024); break; + default: break; + } - g_free (s); - str = size_to_string (size); - } else - str = size_boundary (is_first); + g_free(s); + str = size_to_string(size); + } else + str = size_boundary(is_first); - g_regex_unref (rx); - g_match_info_unref (minfo); + g_regex_unref(rx); + g_match_info_unref(minfo); - return str; + return str; } - std::string Mu::canonicalize_filename(const std::string& path, const std::string& relative_to) { - char *fname = mu_canonicalize_filename ( - path.c_str(), - relative_to.empty() ? NULL : relative_to.c_str()); + char* fname = mu_canonicalize_filename(path.c_str(), + relative_to.empty() ? NULL : relative_to.c_str()); - std::string rv{fname}; - g_free (fname); + std::string rv{fname}; + g_free(fname); - return rv; + return rv; } - void Mu::assert_equal(const std::string& s1, const std::string& s2) { - g_assert_cmpstr (s1.c_str(), ==, s2.c_str()); + g_assert_cmpstr(s1.c_str(), ==, s2.c_str()); } void -Mu::assert_equal (const Mu::StringVec& v1, const Mu::StringVec& v2) +Mu::assert_equal(const Mu::StringVec& v1, const Mu::StringVec& v2) { - g_assert_cmpuint(v1.size(), ==, v2.size()); + g_assert_cmpuint(v1.size(), ==, v2.size()); - for (auto i = 0U; i != v1.size(); ++i) - assert_equal(v1[i], v2[i]); + for (auto i = 0U; i != v1.size(); ++i) + assert_equal(v1[i], v2[i]); } - void Mu::allow_warnings() { - g_test_log_set_fatal_handler( - [](const char*, GLogLevelFlags, const char*, gpointer) { - return FALSE; - },{}); - + g_test_log_set_fatal_handler( + [](const char*, GLogLevelFlags, const char*, gpointer) { return FALSE; }, + {}); } diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh index 651cb266..415f9574 100644 --- a/lib/utils/mu-utils.hh +++ b/lib/utils/mu-utils.hh @@ -28,6 +28,8 @@ #include #include #include +#include +#include namespace Mu { @@ -40,8 +42,12 @@ using StringVec = std::vector; * * @return a flattened string */ -std::string utf8_flatten (const char *str); -inline std::string utf8_flatten (const std::string& s) { return utf8_flatten(s.c_str()); } +std::string utf8_flatten(const char* str); +inline std::string +utf8_flatten(const std::string& s) +{ + return utf8_flatten(s.c_str()); +} /** * Replace all control characters with spaces, and remove leading and trailing space. @@ -50,8 +56,7 @@ inline std::string utf8_flatten (const std::string& s) { return utf8_flatten(s.c * * @return a cleaned-up string. */ -std::string utf8_clean (const std::string& dirty); - +std::string utf8_clean(const std::string& dirty); /** * Remove ctrl characters, replacing them with ' '; subsequent @@ -61,10 +66,7 @@ std::string utf8_clean (const std::string& dirty); * * @return the string without control characters */ -std::string remove_ctrl (const std::string& str); - - - +std::string remove_ctrl(const std::string& str); /** * Split a string in parts @@ -74,8 +76,7 @@ std::string remove_ctrl (const std::string& str); * * @return the parts. */ -std::vector split (const std::string& str, - const std::string& sepa); +std::vector split(const std::string& str, const std::string& sepa); /** * Quote & escape a string for " and \ @@ -84,7 +85,7 @@ std::vector split (const std::string& str, * * @return quoted string */ -std::string quote (const std::string& str); +std::string quote(const std::string& str); /** * Format a string, printf style @@ -94,7 +95,7 @@ std::string quote (const std::string& str); * * @return a formatted string */ -std::string format (const char *frm, ...) __attribute__((format(printf, 1, 2))); +std::string format(const char* frm, ...) __attribute__((format(printf, 1, 2))); /** * Format a string, printf style @@ -104,8 +105,7 @@ std::string format (const char *frm, ...) __attribute__((format(printf, 1, 2))); * * @return a formatted string */ -std::string vformat (const char *frm, va_list args) __attribute__((format(printf, 1, 0))); - +std::string vformat(const char* frm, va_list args) __attribute__((format(printf, 1, 0))); /** * Convert an date to the corresponding time expressed as a string with a @@ -118,7 +118,7 @@ std::string vformat (const char *frm, va_list args) __attribute__((format(printf * * @return the corresponding time_t expressed as a string */ -std::string date_to_time_t_string (const std::string& date, bool first); +std::string date_to_time_t_string(const std::string& date, bool first); /** * 64-bit incarnation of time_t expressed as a 10-digit string. Uses 64-bit for the time-value, @@ -128,37 +128,52 @@ std::string date_to_time_t_string (const std::string& date, bool first); * * @return */ -std::string date_to_time_t_string (int64_t t); +std::string date_to_time_t_string(int64_t t); using Clock = std::chrono::steady_clock; using Duration = Clock::duration; -template constexpr int64_t to_unit (Duration d) { - using namespace std::chrono; - return duration_cast(d).count(); +template +constexpr int64_t +to_unit(Duration d) +{ + using namespace std::chrono; + return duration_cast(d).count(); } -constexpr int64_t to_s (Duration d) { return to_unit(d); } -constexpr int64_t to_ms (Duration d) { return to_unit(d); } -constexpr int64_t to_us (Duration d) { return to_unit(d); } +constexpr int64_t +to_s(Duration d) +{ + return to_unit(d); +} +constexpr int64_t +to_ms(Duration d) +{ + return to_unit(d); +} +constexpr int64_t +to_us(Duration d) +{ + return to_unit(d); +} struct StopWatch { - using Clock = std::chrono::steady_clock; - StopWatch (const std::string name): - start_{Clock::now()}, - name_{name} {} - ~StopWatch() { - const auto us{to_us(Clock::now()-start_)}; - if (us > 2000000) - g_debug ("%s: finished after %0.1f s", name_.c_str(), us/1000000.0); - else if (us > 2000) - g_debug ("%s: finished after %0.1f ms", name_.c_str(), us/1000.0); - else - g_debug ("%s: finished after %" G_GINT64_FORMAT " us", name_.c_str(), us); - } -private: - Clock::time_point start_; - std::string name_; + using Clock = std::chrono::steady_clock; + StopWatch(const std::string name) : start_{Clock::now()}, name_{name} {} + ~StopWatch() + { + const auto us{to_us(Clock::now() - start_)}; + if (us > 2000000) + g_debug("%s: finished after %0.1f s", name_.c_str(), us / 1000000.0); + else if (us > 2000) + g_debug("%s: finished after %0.1f ms", name_.c_str(), us / 1000.0); + else + g_debug("%s: finished after %" G_GINT64_FORMAT " us", name_.c_str(), us); + } + + private: + Clock::time_point start_; + std::string name_; }; /** @@ -179,7 +194,7 @@ std::string canonicalize_filename(const std::string& path, const std::string& re * * @return the size expressed as a string with the decimal number of bytes */ -std::string size_to_string (const std::string& sizestr, bool first); +std::string size_to_string(const std::string& sizestr, bool first); /** * Convert a size into a size in bytes string @@ -189,8 +204,7 @@ std::string size_to_string (const std::string& sizestr, bool first); * * @return the size expressed as a string with the decimal number of bytes */ -std::string size_to_string (int64_t size); - +std::string size_to_string(int64_t size); /** * Convert any ostreamable<< value to a string @@ -200,137 +214,98 @@ std::string size_to_string (int64_t size); * @return a std::string */ template -static inline std::string to_string (const T& val) +static inline std::string +to_string(const T& val) { - std::stringstream sstr; - sstr << val; + std::stringstream sstr; + sstr << val; - return sstr.str(); + return sstr.str(); } - struct MaybeAnsi { - explicit MaybeAnsi(bool use_color): color_{use_color} {} + explicit MaybeAnsi(bool use_color) : color_{use_color} {} - enum struct Color { - Black = 30, - Red = 31, - Green = 32, - Yellow = 33, - Blue = 34, - Magenta = 35, - Cyan = 36, - White = 37, + enum struct Color { + Black = 30, + Red = 31, + Green = 32, + Yellow = 33, + Blue = 34, + Magenta = 35, + Cyan = 36, + White = 37, - BrightBlack = 90, - BrightRed = 91, - BrightGreen = 92, - BrightYellow = 93, - BrightBlue = 94, - BrightMagenta = 95, - BrightCyan = 96, - BrightWhite = 97, - }; + BrightBlack = 90, + BrightRed = 91, + BrightGreen = 92, + BrightYellow = 93, + BrightBlue = 94, + BrightMagenta = 95, + BrightCyan = 96, + BrightWhite = 97, + }; - std::string fg(Color c) const { return ansi(c, true); } - std::string bg(Color c) const { return ansi(c, false); } + std::string fg(Color c) const { return ansi(c, true); } + std::string bg(Color c) const { return ansi(c, false); } - std::string reset() const { return color_ ? "\x1b[0m" : ""; } + std::string reset() const { return color_ ? "\x1b[0m" : ""; } -private: - std::string ansi(Color c, bool fg=true) const { - return color_ ? format("\x1b[%dm", static_cast(c) + (fg ? 0 : 10)) : ""; - } + private: + std::string ansi(Color c, bool fg = true) const + { + return color_ ? format("\x1b[%dm", static_cast(c) + (fg ? 0 : 10)) : ""; + } - const bool color_; + const bool color_; }; -/** - * - * don't repeat these catch blocks everywhere... - * - */ - -#define MU_XAPIAN_CATCH_BLOCK \ - catch (const Xapian::Error &xerr) { \ - g_critical ("%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - } catch (const std::runtime_error& re) { \ - g_critical ("%s: error: %s", __func__, re.what()); \ - } catch (...) { \ - g_critical ("%s: caught exception", __func__); \ - } - -#define MU_XAPIAN_CATCH_BLOCK_G_ERROR(GE,E) \ - catch (const Xapian::DatabaseLockError &xerr) { \ - mu_util_g_set_error ((GE), \ - MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK, \ - "%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - } catch (const Xapian::DatabaseError &xerr) { \ - mu_util_g_set_error ((GE),MU_ERROR_XAPIAN, \ - "%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - } catch (const Xapian::Error &xerr) { \ - mu_util_g_set_error ((GE),(E), \ - "%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - } catch (const std::runtime_error& ex) { \ - mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ - "%s: error: %s", __func__, ex.what()); \ - \ - } catch (...) { \ - mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ - "%s: caught exception", __func__); \ - } - - -#define MU_XAPIAN_CATCH_BLOCK_RETURN(R) \ - catch (const Xapian::Error &xerr) { \ - g_critical ("%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - return (R); \ - } catch (const std::runtime_error& ex) { \ - g_critical("%s: error: %s", __func__, ex.what()); \ - return (R); \ - } catch (...) { \ - g_critical ("%s: caught exception", __func__); \ - return (R); \ - } - -#define MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(GE,E,R) \ - catch (const Xapian::Error &xerr) { \ - mu_util_g_set_error ((GE),(E), \ - "%s: xapian error '%s'", \ - __func__, xerr.get_msg().c_str()); \ - return (R); \ - } catch (const std::runtime_error& ex) { \ - mu_util_g_set_error ((GE),(MU_ERROR_INTERNAL), \ - "%s: error: %s", __func__, ex.what()); \ - return (R); \ - } catch (...) { \ - if ((GE)&&!(*(GE))) \ - mu_util_g_set_error ((GE), \ - (MU_ERROR_INTERNAL), \ - "%s: caught exception", __func__); \ - return (R); \ - } - - +template +void +xapian_try(Func&& func) noexcept +try { + func(); +} catch (const Xapian::Error& xerr) { + g_critical("%s: xapian error '%s'", __func__, xerr.get_msg().c_str()); +} catch (const std::runtime_error& re) { + g_critical("%s: error: %s", __func__, re.what()); +} catch (...) { + g_critical("%s: caught exception", __func__); +} +template > +auto +xapian_try(Func&& func, Default&& def) noexcept -> std::decay_t +try { + return func(); +} catch (const Xapian::Error& xerr) { + g_critical("%s: xapian error '%s'", __func__, xerr.get_msg().c_str()); + return static_cast(def); +} catch (const std::runtime_error& re) { + g_critical("%s: error: %s", __func__, re.what()); + return static_cast(def); +} catch (...) { + g_critical("%s: caught exception", __func__); + return static_cast(def); +} /// Allow using enum structs as bitflags -#define MU_TO_NUM(ET,ELM) std::underlying_type_t(ELM) -#define MU_TO_ENUM(ET,NUM) static_cast(NUM) -#define MU_ENABLE_BITOPS(ET) \ - constexpr ET operator& (ET e1, ET e2) { return MU_TO_ENUM(ET,MU_TO_NUM(ET,e1)&MU_TO_NUM(ET,e2)); } \ - constexpr ET operator| (ET e1, ET e2) { return MU_TO_ENUM(ET,MU_TO_NUM(ET,e1)|MU_TO_NUM(ET,e2)); } \ - constexpr ET operator~ (ET e) { return MU_TO_ENUM(ET,~(MU_TO_NUM(ET, e))); } \ - constexpr bool any_of(ET e) { return MU_TO_NUM(ET,e) != 0; } \ - constexpr bool none_of(ET e) { return MU_TO_NUM(ET,e) == 0; } \ - static inline ET& operator&=(ET& e1, ET e2) { return e1 = e1 & e2;} \ - static inline ET& operator|=(ET& e1, ET e2) { return e1 = e1 | e2;} - +#define MU_TO_NUM(ET, ELM) std::underlying_type_t(ELM) +#define MU_TO_ENUM(ET, NUM) static_cast(NUM) +#define MU_ENABLE_BITOPS(ET) \ + constexpr ET operator&(ET e1, ET e2) \ + { \ + return MU_TO_ENUM(ET, MU_TO_NUM(ET, e1) & MU_TO_NUM(ET, e2)); \ + } \ + constexpr ET operator|(ET e1, ET e2) \ + { \ + return MU_TO_ENUM(ET, MU_TO_NUM(ET, e1) | MU_TO_NUM(ET, e2)); \ + } \ + constexpr ET operator~(ET e) { return MU_TO_ENUM(ET, ~(MU_TO_NUM(ET, e))); } \ + constexpr bool any_of(ET e) { return MU_TO_NUM(ET, e) != 0; } \ + constexpr bool none_of(ET e) { return MU_TO_NUM(ET, e) == 0; } \ + static inline ET& operator&=(ET& e1, ET e2) { return e1 = e1 & e2; } \ + static inline ET& operator|=(ET& e1, ET e2) { return e1 = e1 | e2; } /** * For unit tests, assert two std::string's are equal. @@ -345,7 +320,7 @@ void assert_equal(const std::string& s1, const std::string& s2); * @param c1 container1 * @param c2 container2 */ -void assert_equal (const StringVec& v1, const StringVec& v2); +void assert_equal(const StringVec& v1, const StringVec& v2); /** * For unit-tests, allow warnings in the current function. @@ -355,5 +330,4 @@ void allow_warnings(); } // namespace Mu - #endif /* __MU_UTILS_HH__ */ diff --git a/lib/utils/test-command-parser.cc b/lib/utils/test-command-parser.cc index fc1b57c5..44c9a9cd 100644 --- a/lib/utils/test-command-parser.cc +++ b/lib/utils/test-command-parser.cc @@ -31,120 +31,118 @@ using namespace Mu; static void test_param_getters() { - const auto sexp { Sexp::make_parse(R"((foo :bar 123 :cuux "456" :boo nil :bah true))")}; + const auto sexp{Sexp::make_parse(R"((foo :bar 123 :cuux "456" :boo nil :bah true))")}; - if (g_test_verbose()) - std::cout << sexp << "\n"; + if (g_test_verbose()) + std::cout << sexp << "\n"; - g_assert_cmpint(Command::get_int_or(sexp.list(), ":bar"), ==, 123); - assert_equal(Command::get_string_or(sexp.list(), ":bra", "bla"), "bla"); - assert_equal(Command::get_string_or(sexp.list(), ":cuux"), "456"); + g_assert_cmpint(Command::get_int_or(sexp.list(), ":bar"), ==, 123); + assert_equal(Command::get_string_or(sexp.list(), ":bra", "bla"), "bla"); + assert_equal(Command::get_string_or(sexp.list(), ":cuux"), "456"); - g_assert_true(Command::get_bool_or(sexp.list(),":boo") == false); - g_assert_true(Command::get_bool_or(sexp.list(),":bah") == true); + g_assert_true(Command::get_bool_or(sexp.list(), ":boo") == false); + g_assert_true(Command::get_bool_or(sexp.list(), ":bah") == true); } - static bool -call (const Command::CommandMap& cmap, const std::string& str) try -{ - const auto sexp{Sexp::make_parse(str)}; - invoke (cmap, sexp); +call(const Command::CommandMap& cmap, const std::string& str) +try { + const auto sexp{Sexp::make_parse(str)}; + invoke(cmap, sexp); - return true; + return true; } catch (const Error& err) { - g_warning ("%s", err.what()); - return false; + g_warning("%s", err.what()); + return false; } static void test_command() { - using namespace Command; - allow_warnings(); + using namespace Command; + allow_warnings(); - CommandMap cmap; + CommandMap cmap; - cmap.emplace("my-command", - CommandInfo{ - ArgMap{ {":param1", ArgInfo{Sexp::Type::String, true, "some string" }}, - {":param2", ArgInfo{Sexp::Type::Number, false, "some integer"}}}, - "My command,", - {}}); + cmap.emplace( + "my-command", + CommandInfo{ArgMap{{":param1", ArgInfo{Sexp::Type::String, true, "some string"}}, + {":param2", ArgInfo{Sexp::Type::Number, false, "some integer"}}}, + "My command,", + {}}); - g_assert_true(call(cmap, "(my-command :param1 \"hello\")")); - g_assert_true(call(cmap, "(my-command :param1 \"hello\" :param2 123)")); + g_assert_true(call(cmap, "(my-command :param1 \"hello\")")); + g_assert_true(call(cmap, "(my-command :param1 \"hello\" :param2 123)")); - g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 123 :param3 xxx)")); + g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 123 :param3 xxx)")); } static void test_command2() { - using namespace Command; - allow_warnings(); + using namespace Command; + allow_warnings(); - CommandMap cmap; - cmap.emplace("bla", - CommandInfo{ - ArgMap{ - {":foo", ArgInfo{Sexp::Type::Number, false, "foo"}}, - {":bar", ArgInfo{Sexp::Type::String, false, "bar"}}, - },"yeah", - [&](const auto& params){}}); + CommandMap cmap; + cmap.emplace("bla", + CommandInfo{ArgMap{ + {":foo", ArgInfo{Sexp::Type::Number, false, "foo"}}, + {":bar", ArgInfo{Sexp::Type::String, false, "bar"}}, + }, + "yeah", + [&](const auto& params) {}}); - - g_assert_true (call(cmap, "(bla :foo nil)")); - g_assert_false (call(cmap, "(bla :foo nil :bla nil)")); + g_assert_true(call(cmap, "(bla :foo nil)")); + g_assert_false(call(cmap, "(bla :foo nil :bla nil)")); } - static void test_command_fail() { - using namespace Command; + using namespace Command; - allow_warnings(); + allow_warnings(); - CommandMap cmap; + CommandMap cmap; - cmap.emplace("my-command", - CommandInfo{ - ArgMap{ {":param1", ArgInfo{Sexp::Type::String, true, "some string" }}, - {":param2", ArgInfo{Sexp::Type::Number, false, "some integer"}}}, - "My command,", - {}}); + cmap.emplace( + "my-command", + CommandInfo{ArgMap{{":param1", ArgInfo{Sexp::Type::String, true, "some string"}}, + {":param2", ArgInfo{Sexp::Type::Number, false, "some integer"}}}, + "My command,", + {}}); - g_assert_false (call(cmap, "(my-command)")); - g_assert_false (call(cmap, "(my-command2)")); - g_assert_false(call(cmap, "(my-command :param1 123 :param2 123)")); - g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 \"123\")")); + g_assert_false(call(cmap, "(my-command)")); + g_assert_false(call(cmap, "(my-command2)")); + g_assert_false(call(cmap, "(my-command :param1 123 :param2 123)")); + g_assert_false(call(cmap, "(my-command :param1 \"hello\" :param2 \"123\")")); } - -static void black_hole() {} +static void +black_hole() +{ +} int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/utils/command-parser/param-getters", test_param_getters); - g_test_add_func ("/utils/command-parser/command", test_command); - g_test_add_func ("/utils/command-parser/command2", test_command2); - g_test_add_func ("/utils/command-parser/command-fail", test_command_fail); + g_test_add_func("/utils/command-parser/param-getters", test_param_getters); + g_test_add_func("/utils/command-parser/command", test_command); + g_test_add_func("/utils/command-parser/command2", test_command2); + g_test_add_func("/utils/command-parser/command-fail", test_command_fail); - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| - G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); - - - return g_test_run (); + g_log_set_handler( + NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); + return g_test_run(); } catch (const std::runtime_error& re) { - std::cerr << re.what() << "\n"; - return 1; + std::cerr << re.what() << "\n"; + return 1; } diff --git a/lib/utils/test-option.cc b/lib/utils/test-option.cc index 1826aef3..3313afb1 100644 --- a/lib/utils/test-option.cc +++ b/lib/utils/test-option.cc @@ -23,37 +23,37 @@ using namespace Mu; static Option -get_opt_int (bool b) +get_opt_int(bool b) { - if (b) - return Some(123); - else - return Nothing; + if (b) + return Some(123); + else + return Nothing; } static void test_option() { - { - const auto oi{get_opt_int(true)}; - g_assert_true(!!oi); - g_assert_cmpint(oi.value(),==,123); - } + { + const auto oi{get_opt_int(true)}; + g_assert_true(!!oi); + g_assert_cmpint(oi.value(), ==, 123); + } - { - const auto oi{get_opt_int(false)}; - g_assert_false(!!oi); - g_assert_false(oi.has_value()); - g_assert_cmpint(oi.value_or(456),==,456); - } + { + const auto oi{get_opt_int(false)}; + g_assert_false(!!oi); + g_assert_false(oi.has_value()); + g_assert_cmpint(oi.value_or(456), ==, 456); + } } int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/option/option", test_option); + g_test_add_func("/option/option", test_option); - return g_test_run (); + return g_test_run(); } diff --git a/lib/utils/test-sexp.cc b/lib/utils/test-sexp.cc index 0e2d5b28..d6e2145c 100644 --- a/lib/utils/test-sexp.cc +++ b/lib/utils/test-sexp.cc @@ -29,122 +29,122 @@ using namespace Mu; static bool -check_parse (const std::string& expr, const std::string& expected) +check_parse(const std::string& expr, const std::string& expected) { - try { - const auto parsed{to_string(Sexp::make_parse(expr))}; - assert_equal(parsed, expected); - return true; + try { + const auto parsed{to_string(Sexp::make_parse(expr))}; + assert_equal(parsed, expected); + return true; - } catch (const Error& err) { - g_warning ("caught exception parsing '%s': %s", expr.c_str(), err.what()); - return false; - } + } catch (const Error& err) { + g_warning("caught exception parsing '%s': %s", expr.c_str(), err.what()); + return false; + } } static void test_parser() { - check_parse(":foo-123", ":foo-123"); - check_parse("foo", "foo"); - check_parse(R"(12345)", "12345"); - check_parse(R"(-12345)", "-12345"); - check_parse(R"((123 bar "cuux"))", "(123 bar \"cuux\")"); + check_parse(":foo-123", ":foo-123"); + check_parse("foo", "foo"); + check_parse(R"(12345)", "12345"); + check_parse(R"(-12345)", "-12345"); + check_parse(R"((123 bar "cuux"))", "(123 bar \"cuux\")"); - check_parse(R"("foo\"bar\"cuux")", "\"foo\\\"bar\\\"cuux\""); + check_parse(R"("foo\"bar\"cuux")", "\"foo\\\"bar\\\"cuux\""); - check_parse(R"("foo -bar")", "\"foo\nbar\""); + check_parse(R"("foo +bar")", + "\"foo\nbar\""); } static void test_list() { - const auto nstr{Sexp::make_string("foo")}; - g_assert_true(nstr.value() == "foo"); - g_assert_true(nstr.type() == Sexp::Type::String); - assert_equal(nstr.to_sexp_string(), "\"foo\""); + const auto nstr{Sexp::make_string("foo")}; + g_assert_true(nstr.value() == "foo"); + g_assert_true(nstr.type() == Sexp::Type::String); + assert_equal(nstr.to_sexp_string(), "\"foo\""); - const auto nnum{Sexp::make_number(123)}; - g_assert_true(nnum.value() == "123"); - g_assert_true(nnum.type() == Sexp::Type::Number); - assert_equal(nnum.to_sexp_string(), "123"); + const auto nnum{Sexp::make_number(123)}; + g_assert_true(nnum.value() == "123"); + g_assert_true(nnum.type() == Sexp::Type::Number); + assert_equal(nnum.to_sexp_string(), "123"); - const auto nsym{Sexp::make_symbol("blub")}; - g_assert_true(nsym.value() == "blub"); - g_assert_true(nsym.type() == Sexp::Type::Symbol); - assert_equal(nsym.to_sexp_string(), "blub"); + const auto nsym{Sexp::make_symbol("blub")}; + g_assert_true(nsym.value() == "blub"); + g_assert_true(nsym.type() == Sexp::Type::Symbol); + assert_equal(nsym.to_sexp_string(), "blub"); - Sexp::List list; - list .add(Sexp::make_string("foo")) - .add(Sexp::make_number(123)) - .add(Sexp::make_symbol("blub")); + Sexp::List list; + list.add(Sexp::make_string("foo")) + .add(Sexp::make_number(123)) + .add(Sexp::make_symbol("blub")); - const auto nlst = Sexp::make_list(std::move(list)); - g_assert_true(nlst.list().size() == 3); - g_assert_true(nlst.type() == Sexp::Type::List); - g_assert_true(nlst.list().at(1).value() == "123"); + const auto nlst = Sexp::make_list(std::move(list)); + g_assert_true(nlst.list().size() == 3); + g_assert_true(nlst.type() == Sexp::Type::List); + g_assert_true(nlst.list().at(1).value() == "123"); - assert_equal(nlst.to_sexp_string(),"(\"foo\" 123 blub)"); + assert_equal(nlst.to_sexp_string(), "(\"foo\" 123 blub)"); } - static void test_prop_list() { - Sexp::List l1; - l1.add_prop(":foo", Sexp::make_string("bar")); - Sexp s2{Sexp::make_list(std::move(l1))}; - assert_equal(s2.to_sexp_string(), "(:foo \"bar\")"); + Sexp::List l1; + l1.add_prop(":foo", Sexp::make_string("bar")); + Sexp s2{Sexp::make_list(std::move(l1))}; + assert_equal(s2.to_sexp_string(), "(:foo \"bar\")"); - - Sexp::List l2; - const std::string x{"bar"}; - l2.add_prop(":foo", Sexp::make_string(x)); - l2.add_prop(":bar", Sexp::make_number(77)); - Sexp::List l3; - l3.add_prop(":cuux", Sexp::make_list(std::move(l2))); - Sexp s3{Sexp::make_list(std::move(l3))}; - assert_equal(s3.to_sexp_string(), "(:cuux (:foo \"bar\" :bar 77))"); + Sexp::List l2; + const std::string x{"bar"}; + l2.add_prop(":foo", Sexp::make_string(x)); + l2.add_prop(":bar", Sexp::make_number(77)); + Sexp::List l3; + l3.add_prop(":cuux", Sexp::make_list(std::move(l2))); + Sexp s3{Sexp::make_list(std::move(l3))}; + assert_equal(s3.to_sexp_string(), "(:cuux (:foo \"bar\" :bar 77))"); } static void test_props() { - auto sexp2 = Sexp::make_list( - Sexp::make_string("foo"), - Sexp::make_number(123), - Sexp::make_symbol("blub")); + auto sexp2 = Sexp::make_list(Sexp::make_string("foo"), + Sexp::make_number(123), + Sexp::make_symbol("blub")); - auto sexp = Sexp::make_prop_list( - ":foo", Sexp::make_string("bär"), - ":cuux", Sexp::make_number(123), - ":flub", Sexp::make_symbol("fnord"), - ":boo", std::move(sexp2)); + auto sexp = Sexp::make_prop_list(":foo", + Sexp::make_string("bär"), + ":cuux", + Sexp::make_number(123), + ":flub", + Sexp::make_symbol("fnord"), + ":boo", + std::move(sexp2)); - assert_equal(sexp.to_sexp_string(), - "(:foo \"b\303\244r\" :cuux 123 :flub fnord :boo (\"foo\" 123 blub))"); + assert_equal(sexp.to_sexp_string(), + "(:foo \"b\303\244r\" :cuux 123 :flub fnord :boo (\"foo\" 123 blub))"); } int -main (int argc, char *argv[]) try -{ - g_test_init (&argc, &argv, NULL); +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); - if (argc == 2) { - std::cout << Sexp::make_parse(argv[1]) << '\n'; - return 0; - } + if (argc == 2) { + std::cout << Sexp::make_parse(argv[1]) << '\n'; + return 0; + } - g_test_add_func ("/utils/sexp/parser", test_parser); - g_test_add_func ("/utils/sexp/list", test_list); - g_test_add_func ("/utils/sexp/proplist", test_prop_list); - g_test_add_func ("/utils/sexp/props", test_props); - - return g_test_run (); + g_test_add_func("/utils/sexp/parser", test_parser); + g_test_add_func("/utils/sexp/list", test_list); + g_test_add_func("/utils/sexp/proplist", test_prop_list); + g_test_add_func("/utils/sexp/props", test_props); + return g_test_run(); } catch (const std::runtime_error& re) { - std::cerr << re.what() << "\n"; - return 1; + std::cerr << re.what() << "\n"; + return 1; } diff --git a/lib/utils/test-utils.cc b/lib/utils/test-utils.cc index 2972d2f3..811c882a 100644 --- a/lib/utils/test-utils.cc +++ b/lib/utils/test-utils.cc @@ -29,19 +29,17 @@ using namespace Mu; struct Case { - const std::string expr; - bool is_first{}; - const std::string expected; + const std::string expr; + bool is_first{}; + const std::string expected; }; -using CaseVec = std::vector; +using CaseVec = std::vector; using ProcFunc = std::function; - static void test_cases(const CaseVec& cases, ProcFunc proc) { - for (const auto& casus : cases ) { - + for (const auto& casus : cases) { const auto res = proc(casus.expr, casus.is_first); if (g_test_verbose()) { std::cout << "\n"; @@ -50,176 +48,159 @@ test_cases(const CaseVec& cases, ProcFunc proc) std::cout << "got: '" << res << "'" << std::endl; } - g_assert_true (casus.expected == res); + g_assert_true(casus.expected == res); } } static void -test_date_basic () +test_date_basic() { - g_setenv ("TZ", "Europe/Helsinki", TRUE); + g_setenv("TZ", "Europe/Helsinki", TRUE); - CaseVec cases = { - { "2015-09-18T09:10:23", true, "1442556623" }, - { "1972-12-14T09:10:23", true, "0093165023" }, - { "1854-11-18T17:10:23", true, "0000000000" }, + CaseVec cases = {{"2015-09-18T09:10:23", true, "1442556623"}, + {"1972-12-14T09:10:23", true, "0093165023"}, + {"1854-11-18T17:10:23", true, "0000000000"}, - { "2000-02-31T09:10:23", true, "0951861599" }, - { "2000-02-29T23:59:59", true, "0951861599" }, + {"2000-02-31T09:10:23", true, "0951861599"}, + {"2000-02-29T23:59:59", true, "0951861599"}, - { "2016", true, "1451599200" }, - { "2016", false, "1483221599" }, + {"2016", true, "1451599200"}, + {"2016", false, "1483221599"}, - { "fnorb", true, "0000000000" }, - { "fnorb", false, "9999999999" }, - { "", false, "9999999999" }, - { "", true, "0000000000" } - }; + {"fnorb", true, "0000000000"}, + {"fnorb", false, "9999999999"}, + {"", false, "9999999999"}, + {"", true, "0000000000"}}; - test_cases (cases, [](auto s, auto f){ return date_to_time_t_string(s,f); }); + test_cases(cases, [](auto s, auto f) { return date_to_time_t_string(s, f); }); } static void -test_date_ymwdhMs (void) +test_date_ymwdhMs(void) { struct { - std::string expr; - long diff; - int tolerance; - } tests[] = { - { "3h", 3 * 60 * 60, 1 }, - { "21d", 21 * 24 * 60 * 60, 3600 + 1 }, - { "2w", 2 * 7 * 24 * 60 * 60, 3600 + 1 }, + std::string expr; + long diff; + int tolerance; + } tests[] = {{"3h", 3 * 60 * 60, 1}, + {"21d", 21 * 24 * 60 * 60, 3600 + 1}, + {"2w", 2 * 7 * 24 * 60 * 60, 3600 + 1}, - { "2y", 2 * 365 * 24 * 60 * 60, 24 * 3600 + 1 }, - { "3m", 3 * 30 * 24 * 60 * 60, 3 * 24 * 3600 + 1 } - }; + {"2y", 2 * 365 * 24 * 60 * 60, 24 * 3600 + 1}, + {"3m", 3 * 30 * 24 * 60 * 60, 3 * 24 * 3600 + 1}}; for (auto i = 0; i != G_N_ELEMENTS(tests); ++i) { - const auto diff = time(NULL) - - strtol(Mu::date_to_time_t_string(tests[i].expr, true).c_str(), - NULL, 10); + const auto diff = + time(NULL) - + strtol(Mu::date_to_time_t_string(tests[i].expr, true).c_str(), NULL, 10); if (g_test_verbose()) - std::cerr << tests[i].expr << ' ' - << diff << ' ' - << tests[i].diff << std::endl; + std::cerr << tests[i].expr << ' ' << diff << ' ' << tests[i].diff + << std::endl; - g_assert_true (tests[i].diff - diff <= tests[i].tolerance); + g_assert_true(tests[i].diff - diff <= tests[i].tolerance); } - g_assert_true (strtol(Mu::date_to_time_t_string("-1y", true).c_str(), - NULL, 10) == 0); + g_assert_true(strtol(Mu::date_to_time_t_string("-1y", true).c_str(), NULL, 10) == 0); } static void -test_size () +test_size() { CaseVec cases = { - { "456", true, "0000000456" }, - { "", false, "9999999999" }, - { "", true, "0000000000" }, + {"456", true, "0000000456"}, + {"", false, "9999999999"}, + {"", true, "0000000000"}, }; - test_cases (cases, [](auto s, auto f){ return size_to_string(s,f); }); + test_cases(cases, [](auto s, auto f) { return size_to_string(s, f); }); } - static void -test_flatten () +test_flatten() { CaseVec cases = { - { "Менделе́ев", true, "менделеев" }, - { "", false, "" }, - { "Ångström", true, "angstrom" }, + {"Менделе́ев", true, "менделеев"}, + {"", false, ""}, + {"Ångström", true, "angstrom"}, }; - test_cases (cases, [](auto s, auto f){ return utf8_flatten(s); }); + test_cases(cases, [](auto s, auto f) { return utf8_flatten(s); }); } static void -test_remove_ctrl () +test_remove_ctrl() { CaseVec cases = { - { "Foo\n\nbar", true, "Foo bar" }, - { "", false, "" }, - { " ", false, " " }, - { "Hello World ", false, "Hello World " }, - { "Ångström", false, "Ångström" }, + {"Foo\n\nbar", true, "Foo bar"}, + {"", false, ""}, + {" ", false, " "}, + {"Hello World ", false, "Hello World "}, + {"Ångström", false, "Ångström"}, }; - test_cases (cases, [](auto s, auto f){ return remove_ctrl(s); }); + test_cases(cases, [](auto s, auto f) { return remove_ctrl(s); }); } - - static void -test_clean () +test_clean() { CaseVec cases = { - { "\t a\t\nb ", true, "a b" }, - { "", false, "" }, - { "Ångström", true, "Ångström" }, + {"\t a\t\nb ", true, "a b"}, + {"", false, ""}, + {"Ångström", true, "Ångström"}, }; - test_cases (cases, [](auto s, auto f){ return utf8_clean(s); }); + test_cases(cases, [](auto s, auto f) { return utf8_clean(s); }); } - static void -test_format () +test_format() { - g_assert_true (format ("hello %s", "world") == - "hello world"); - g_assert_true (format ("hello %s, %u", "world", 123) == - "hello world, 123"); + g_assert_true(format("hello %s", "world") == "hello world"); + g_assert_true(format("hello %s, %u", "world", 123) == "hello world, 123"); } - enum struct Bits { None = 0, Bit1 = 1 << 0, Bit2 = 1 << 1 }; MU_ENABLE_BITOPS(Bits); static void test_define_bitmap() { - g_assert_cmpuint((guint)Bits::None,==,(guint)0); - g_assert_cmpuint((guint)Bits::Bit1,==,(guint)1); - g_assert_cmpuint((guint)Bits::Bit2,==,(guint)2); + g_assert_cmpuint((guint)Bits::None, ==, (guint)0); + g_assert_cmpuint((guint)Bits::Bit1, ==, (guint)1); + g_assert_cmpuint((guint)Bits::Bit2, ==, (guint)2); - g_assert_cmpuint((guint)(Bits::Bit1|Bits::Bit2),==,(guint)3); - g_assert_cmpuint((guint)(Bits::Bit1&Bits::Bit2),==,(guint)0); + g_assert_cmpuint((guint)(Bits::Bit1 | Bits::Bit2), ==, (guint)3); + g_assert_cmpuint((guint)(Bits::Bit1 & Bits::Bit2), ==, (guint)0); - g_assert_cmpuint((guint)(Bits::Bit1&(~Bits::Bit2)),==,(guint)1); + g_assert_cmpuint((guint)(Bits::Bit1 & (~Bits::Bit2)), ==, (guint)1); { Bits b{Bits::Bit1}; - b|=Bits::Bit2; - g_assert_cmpuint((guint)b,==,(guint)3); + b |= Bits::Bit2; + g_assert_cmpuint((guint)b, ==, (guint)3); } { Bits b{Bits::Bit1}; - b&=Bits::Bit1; - g_assert_cmpuint((guint)b,==,(guint)1); + b &= Bits::Bit1; + g_assert_cmpuint((guint)b, ==, (guint)1); } - - } - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - g_test_add_func ("/utils/date-basic", test_date_basic); - g_test_add_func ("/utils/date-ymwdhMs", test_date_ymwdhMs); - g_test_add_func ("/utils/size", test_size); - g_test_add_func ("/utils/flatten", test_flatten); - g_test_add_func ("/utils/remove-ctrl", test_remove_ctrl); - g_test_add_func ("/utils/clean", test_clean); - g_test_add_func ("/utils/format", test_format); - g_test_add_func ("/utils/define-bitmap", test_define_bitmap); + g_test_add_func("/utils/date-basic", test_date_basic); + g_test_add_func("/utils/date-ymwdhMs", test_date_ymwdhMs); + g_test_add_func("/utils/size", test_size); + g_test_add_func("/utils/flatten", test_flatten); + g_test_add_func("/utils/remove-ctrl", test_remove_ctrl); + g_test_add_func("/utils/clean", test_clean); + g_test_add_func("/utils/format", test_format); + g_test_add_func("/utils/define-bitmap", test_define_bitmap); - return g_test_run (); + return g_test_run(); } diff --git a/man/mu-script.1 b/man/mu-script.1 index aa4159b8..ec3f0324 100644 --- a/man/mu-script.1 +++ b/man/mu-script.1 @@ -1,8 +1,8 @@ -.TH MU SCRIPT 1 "June 2013" "User Manuals" +.TH MU SCRIPT 1 "October 2021" "User Manuals" .SH NAME -mu script\- show the available mu scripts, and run them. +mu script\- show the available mu scripts, and/or run them. .SH SYNOPSIS @@ -58,8 +58,9 @@ code when this is not the case. .SH FILES You can make your own Scheme scripts accessible through \fBmu script\fR by -putting them in \fI/scripts\fR (which is typically -\fI~/.mu/scripts\fR). It is a good idea to document the scripts by using some +putting them in either \fI/mu/scripts\fR (e.g., \fI~/.local/share/mu/scripts\fR) or, if \fImuhome\fR is specified, in + +It is a good idea to document the scripts by using some special comments in the source code: .nf ;; INFO: this is my script -- one-line description diff --git a/meson.build b/meson.build index dfebd630..cd1337dd 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,7 @@ # project setup # project('mu', ['c', 'cpp'], - version: '1.7.0', + version: '1.7.3', meson_version: '>= 0.52.0', # debian 10 license: 'GPL-3.0-or-later', default_options : [ @@ -78,6 +78,11 @@ config_h_data.set_quoted('PACKAGE_STRING', meson.project_name() + ' ' + config_h_data.set_quoted('VERSION', meson.project_version()) config_h_data.set_quoted('PACKAGE_NAME', meson.project_name()) +add_project_arguments(['-DHAVE_CONFIG_H'], language: 'c') +add_project_arguments(['-DHAVE_CONFIG_H'], language: 'cpp') +config_h_dep=declare_dependency( + include_directories: include_directories(['.'])) + functions=[ 'setsid' ] @@ -103,6 +108,14 @@ gmime_dep = dependency('gmime-3.0', version: '>= 3.2') xapian_dep = dependency('xapian-core', version:'>= 1.4') thread_dep = dependency('threads') +# soft dependencies +guile_dep = dependency('guile-3.0', required: get_option('guile')) + +if get_option('toys').enabled() + gtk_dep = dependency('gtk+-3.0') + webkit_dep = dependency('webkit2gtk-4.0') +endif + awk=find_program(['gawk', 'awk']) # soft dependencies @@ -129,29 +142,6 @@ if get_option('readline').enabled() config_h_data.set('HAVE_READLINE_HISTORY_H', 1) endif -# guile -guile_deps=[] -if get_option('guile').enabled() - guile_dep = dependency('guile-3.0') -endif - -# toys. -gtk_dep=[] -webkit_dep=[] -if get_option('toys').enabled() - gtk_dep = dependency('gtk+-3.0') - webkit_dep = dependency('webkit2gtk-4.0') -endif - - -################################################################################ -# write-out config.h. -configure_file(output : 'config.h', configuration : config_h_data) -add_project_arguments(['-DHAVE_CONFIG_H'], language: 'c') -add_project_arguments(['-DHAVE_CONFIG_H'], language: 'cpp') -config_h_dep=declare_dependency( - include_directories: include_directories(['.'])) - ################################################################################ # write out version.texi (for texiinfo builds in mu4e, guile) @@ -184,7 +174,9 @@ if emacs.found() subdir('mu4e') endif -if get_option('guile').enabled() +if not get_option('guile').disabled() and guile_dep.found() + config_h_data.set('BUILD_GUILE', 1) + config_h_data.set('GUILE_BINARY', '"guile"') subdir('guile') endif @@ -192,3 +184,7 @@ if get_option('toys').enabled() subdir('toys/mug') endif ################################################################################ + +################################################################################ +# write-out config.h +configure_file(output : 'config.h', configuration : config_h_data) diff --git a/mu/mu-cmd-cfind.cc b/mu/mu-cmd-cfind.cc index 9b163e2a..dc5709cd 100644 --- a/mu/mu-cmd-cfind.cc +++ b/mu/mu-cmd-cfind.cc @@ -47,16 +47,16 @@ using namespace Mu; * g_free) */ static gchar* -guess_last_name (const char *name) +guess_last_name(const char* name) { - const gchar *lastsp; + const gchar* lastsp; - if (!name) - return g_strdup (""); + if (!name) + return g_strdup(""); - lastsp = g_strrstr (name, " "); + lastsp = g_strrstr(name, " "); - return g_strdup (lastsp ? lastsp + 1 : ""); + return g_strdup(lastsp ? lastsp + 1 : ""); } /** @@ -69,19 +69,19 @@ guess_last_name (const char *name) * g_free) */ static gchar* -guess_first_name (const char *name) +guess_first_name(const char* name) { - const gchar *lastsp; + const gchar* lastsp; - if (!name) - return g_strdup (""); + if (!name) + return g_strdup(""); - lastsp = g_strrstr (name, " "); + lastsp = g_strrstr(name, " "); - if (lastsp) - return g_strndup (name, lastsp - name); - else - return g_strdup (name); + if (lastsp) + return g_strndup(name, lastsp - name); + else + return g_strdup(name); } /** @@ -95,336 +95,322 @@ guess_first_name (const char *name) * @return the guessed nick, as a newly allocated string (free with g_free) */ static gchar* -cleanup_str (const char* str) +cleanup_str(const char* str) { - gchar *s; - const gchar *cur; - unsigned i; + gchar* s; + const gchar* cur; + unsigned i; - if (mu_str_is_empty(str)) - return g_strdup (""); + if (mu_str_is_empty(str)) + return g_strdup(""); - s = g_new0 (char, strlen(str) + 1); + s = g_new0(char, strlen(str) + 1); - for (cur = str, i = 0; *cur; ++cur) { - if (ispunct(*cur) || isspace(*cur)) - continue; - else - s[i++] = *cur; - } + for (cur = str, i = 0; *cur; ++cur) { + if (ispunct(*cur) || isspace(*cur)) + continue; + else + s[i++] = *cur; + } - return s; + return s; } static char* -uniquify_nick (const char *nick, GHashTable *nicks) +uniquify_nick(const char* nick, GHashTable* nicks) { - guint u; + guint u; - for (u = 2; u != 1000; ++u) { - char *cand; - cand = g_strdup_printf ("%s%u", nick, u); - if (!g_hash_table_contains (nicks, cand)) - return cand; - } + for (u = 2; u != 1000; ++u) { + char* cand; + cand = g_strdup_printf("%s%u", nick, u); + if (!g_hash_table_contains(nicks, cand)) + return cand; + } - return g_strdup (nick); /* if all else fails */ + return g_strdup(nick); /* if all else fails */ } - static gchar* -guess_nick (const char* name, GHashTable *nicks) +guess_nick(const char* name, GHashTable* nicks) { - gchar *fname, *lname, *nick; - gchar initial[7]; + gchar *fname, *lname, *nick; + gchar initial[7]; - fname = guess_first_name (name); - lname = guess_last_name (name); + fname = guess_first_name(name); + lname = guess_last_name(name); - /* if there's no last name, use first name as the nick */ - if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) { - g_free (lname); - nick = fname; - goto leave; - } + /* if there's no last name, use first name as the nick */ + if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) { + g_free(lname); + nick = fname; + goto leave; + } - memset (initial, 0, sizeof(initial)); - /* couldn't we get an initial for the last name? */ - if (g_unichar_to_utf8 (g_utf8_get_char (lname), initial) == 0) { - g_free (lname); - nick = fname; - goto leave; - } + memset(initial, 0, sizeof(initial)); + /* couldn't we get an initial for the last name? */ + if (g_unichar_to_utf8(g_utf8_get_char(lname), initial) == 0) { + g_free(lname); + nick = fname; + goto leave; + } - nick = g_strdup_printf ("%s%s", fname, initial); - g_free (fname); - g_free (lname); + nick = g_strdup_printf("%s%s", fname, initial); + g_free(fname); + g_free(lname); -leave: - { - gchar *tmp; - tmp = cleanup_str (nick); - g_free (nick); - nick = tmp; - } +leave : { + gchar* tmp; + tmp = cleanup_str(nick); + g_free(nick); + nick = tmp; +} - if (g_hash_table_contains (nicks, nick)) { - char *tmp; - tmp = uniquify_nick (nick, nicks); - g_free (nick); - nick = tmp; - } + if (g_hash_table_contains(nicks, nick)) { + char* tmp; + tmp = uniquify_nick(nick, nicks); + g_free(nick); + nick = tmp; + } - g_hash_table_add (nicks, g_strdup(nick)); + g_hash_table_add(nicks, g_strdup(nick)); - return nick; + return nick; } static void -print_header (const MuConfigFormat format) +print_header(const MuConfigFormat format) { - switch (format) { - case MU_CONFIG_FORMAT_BBDB: - g_print (";; -*-coding: utf-8-emacs;-*-\n" - ";;; file-version: 6\n"); - break; - case MU_CONFIG_FORMAT_MUTT_AB: - g_print ("Matching addresses in the mu database:\n"); - break; - default: - break; - } + switch (format) { + case MU_CONFIG_FORMAT_BBDB: + g_print(";; -*-coding: utf-8-emacs;-*-\n" + ";;; file-version: 6\n"); + break; + case MU_CONFIG_FORMAT_MUTT_AB: g_print("Matching addresses in the mu database:\n"); break; + default: break; + } } static void -each_contact_bbdb (const std::string& email, const std::string& name, time_t tstamp) +each_contact_bbdb(const std::string& email, const std::string& name, time_t tstamp) { - char *fname, *lname, *now, *timestamp; + char *fname, *lname, *now, *timestamp; - fname = guess_first_name (name.c_str()); - lname = guess_last_name (name.c_str()); - now = mu_date_str ("%Y-%m-%d", time(NULL)); - timestamp = mu_date_str ("%Y-%m-%d", tstamp); + fname = guess_first_name(name.c_str()); + lname = guess_last_name(name.c_str()); + now = mu_date_str("%Y-%m-%d", time(NULL)); + timestamp = mu_date_str("%Y-%m-%d", tstamp); - g_print ("[\"%s\" \"%s\" nil nil nil nil (\"%s\") " - "((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n", - fname, lname, email.c_str(), now, timestamp); + g_print("[\"%s\" \"%s\" nil nil nil nil (\"%s\") " + "((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n", + fname, + lname, + email.c_str(), + now, + timestamp); - g_free (now); - g_free (timestamp); - g_free (fname); - g_free (lname); -} - - -static void -each_contact_mutt_alias (const std::string& email, const std::string& name, - GHashTable *nicks) -{ - if (name.empty()) - return; - - char *nick = guess_nick (name.c_str(), nicks); - mu_util_print_encoded ("alias %s %s <%s>\n", - nick, name.c_str(), email.c_str()); - g_free (nick); -} - - -static void -each_contact_wl (const std::string& email, const std::string& name, GHashTable *nicks) -{ - if (name.empty()) - return; - - char *nick = guess_nick (name.c_str(), nicks); - mu_util_print_encoded ("%s \"%s\" \"%s\"\n", email.c_str(), nick, name.c_str()); - g_free (nick); + g_free(now); + g_free(timestamp); + g_free(fname); + g_free(lname); } static void -print_plain (const std::string& email, const std::string& name, bool color) +each_contact_mutt_alias(const std::string& email, const std::string& name, GHashTable* nicks) { - if (!name.empty()) { - if (color) - ::fputs (MU_COLOR_MAGENTA, stdout); - mu_util_fputs_encoded (name.c_str(), stdout); - ::fputs (" ", stdout); - } + if (name.empty()) + return; - if (color) - ::fputs (MU_COLOR_GREEN, stdout); + char* nick = guess_nick(name.c_str(), nicks); + mu_util_print_encoded("alias %s %s <%s>\n", nick, name.c_str(), email.c_str()); + g_free(nick); +} - mu_util_fputs_encoded (email.c_str(), stdout); +static void +each_contact_wl(const std::string& email, const std::string& name, GHashTable* nicks) +{ + if (name.empty()) + return; - if (color) - fputs (MU_COLOR_DEFAULT, stdout); + char* nick = guess_nick(name.c_str(), nicks); + mu_util_print_encoded("%s \"%s\" \"%s\"\n", email.c_str(), nick, name.c_str()); + g_free(nick); +} - fputs ("\n", stdout); +static void +print_plain(const std::string& email, const std::string& name, bool color) +{ + if (!name.empty()) { + if (color) + ::fputs(MU_COLOR_MAGENTA, stdout); + mu_util_fputs_encoded(name.c_str(), stdout); + ::fputs(" ", stdout); + } + + if (color) + ::fputs(MU_COLOR_GREEN, stdout); + + mu_util_fputs_encoded(email.c_str(), stdout); + + if (color) + fputs(MU_COLOR_DEFAULT, stdout); + + fputs("\n", stdout); } struct ECData { - MuConfigFormat format; - gboolean color, personal; - time_t after; - GRegex *rx; - GHashTable *nicks; - size_t n; + MuConfigFormat format; + gboolean color, personal; + time_t after; + GRegex* rx; + GHashTable* nicks; + size_t n; }; static void -each_contact (const Mu::ContactInfo& ci, ECData& ecdata) +each_contact(const Mu::ContactInfo& ci, ECData& ecdata) { - if (ecdata.personal && ci.personal) - return; + if (ecdata.personal && ci.personal) + return; - if (ci.tstamp < ecdata.after) - return; + if (ci.tstamp < ecdata.after) + return; - if (ecdata.rx && - !g_regex_match (ecdata.rx, ci.email.c_str(), (GRegexMatchFlags)0, NULL) && - !g_regex_match (ecdata.rx, ci.name.empty() ? "" : ci.name.c_str(), (GRegexMatchFlags)0, NULL)) - return; + if (ecdata.rx && !g_regex_match(ecdata.rx, ci.email.c_str(), (GRegexMatchFlags)0, NULL) && + !g_regex_match(ecdata.rx, + ci.name.empty() ? "" : ci.name.c_str(), + (GRegexMatchFlags)0, + NULL)) + return; - ++ecdata.n; + ++ecdata.n; - switch (ecdata.format) { - case MU_CONFIG_FORMAT_MUTT_ALIAS: - each_contact_mutt_alias (ci.email, ci.name, ecdata.nicks); - break; - case MU_CONFIG_FORMAT_MUTT_AB: - mu_util_print_encoded ("%s\t%s\t\n", - ci.email.c_str(), ci.name.c_str()); - break; - case MU_CONFIG_FORMAT_WL: - each_contact_wl (ci.email, ci.name, ecdata.nicks); - break; - case MU_CONFIG_FORMAT_ORG_CONTACT: - if (!ci.name.empty()) - mu_util_print_encoded("* %s\n:PROPERTIES:\n:EMAIL: %s\n:END:\n\n", - ci.name.c_str(), ci.email.c_str()); - break; - case MU_CONFIG_FORMAT_BBDB: - each_contact_bbdb (ci.email, ci.name, ci.last_seen); - break; - case MU_CONFIG_FORMAT_CSV: - mu_util_print_encoded("%s,%s\n", - ci.name.empty() ? "" : Mu::quote(ci.name).c_str(), - Mu::quote(ci.email).c_str()); - break; - case MU_CONFIG_FORMAT_DEBUG: { - char datebuf[32]; - strftime(datebuf, sizeof(datebuf), "%F %T", - gmtime(&ci.last_seen)); - g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n" - "\tlast-seen: %s\n", - ci.email.c_str(), - ci.name.empty() ? "" : ci.name.c_str(), - ci.full_address.c_str(), - ci.personal ? "yes" : "no", - ci.freq, - datebuf); - } break; - default: - print_plain (ci.email, ci.name, ecdata.color); - } + switch (ecdata.format) { + case MU_CONFIG_FORMAT_MUTT_ALIAS: + each_contact_mutt_alias(ci.email, ci.name, ecdata.nicks); + break; + case MU_CONFIG_FORMAT_MUTT_AB: + mu_util_print_encoded("%s\t%s\t\n", ci.email.c_str(), ci.name.c_str()); + break; + case MU_CONFIG_FORMAT_WL: each_contact_wl(ci.email, ci.name, ecdata.nicks); break; + case MU_CONFIG_FORMAT_ORG_CONTACT: + if (!ci.name.empty()) + mu_util_print_encoded("* %s\n:PROPERTIES:\n:EMAIL: %s\n:END:\n\n", + ci.name.c_str(), + ci.email.c_str()); + break; + case MU_CONFIG_FORMAT_BBDB: each_contact_bbdb(ci.email, ci.name, ci.last_seen); break; + case MU_CONFIG_FORMAT_CSV: + mu_util_print_encoded("%s,%s\n", + ci.name.empty() ? "" : Mu::quote(ci.name).c_str(), + Mu::quote(ci.email).c_str()); + break; + case MU_CONFIG_FORMAT_DEBUG: { + char datebuf[32]; + strftime(datebuf, sizeof(datebuf), "%F %T", gmtime(&ci.last_seen)); + g_print("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n" + "\tlast-seen: %s\n", + ci.email.c_str(), + ci.name.empty() ? "" : ci.name.c_str(), + ci.full_address.c_str(), + ci.personal ? "yes" : "no", + ci.freq, + datebuf); + } break; + default: print_plain(ci.email, ci.name, ecdata.color); + } } - static MuError -run_cmd_cfind (const Mu::Store& store, - const char* pattern, - gboolean personal, - time_t after, - const MuConfigFormat format, - gboolean color, - GError **err) +run_cmd_cfind(const Mu::Store& store, + const char* pattern, + gboolean personal, + time_t after, + const MuConfigFormat format, + gboolean color, + GError** err) { - ECData ecdata{}; + ECData ecdata{}; - memset(&ecdata, 0, sizeof(ecdata)); + memset(&ecdata, 0, sizeof(ecdata)); - if (pattern) { - ecdata.rx = g_regex_new (pattern, - (GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE), - (GRegexMatchFlags)0, err); - if (!ecdata.rx) - return MU_ERROR_CONTACTS; - } + if (pattern) { + ecdata.rx = g_regex_new(pattern, + (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE), + (GRegexMatchFlags)0, + err); + if (!ecdata.rx) + return MU_ERROR_CONTACTS; + } - ecdata.personal = personal; - ecdata.n = 0; - ecdata.after = after; - ecdata.format = format; - ecdata.color = color; - ecdata.nicks = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); + ecdata.personal = personal; + ecdata.n = 0; + ecdata.after = after; + ecdata.format = format; + ecdata.color = color; + ecdata.nicks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - print_header (format); + print_header(format); - store.contacts().for_each([&](const auto& ci) { each_contact(ci, ecdata); }); + store.contacts().for_each([&](const auto& ci) { each_contact(ci, ecdata); }); - g_hash_table_unref (ecdata.nicks); + g_hash_table_unref(ecdata.nicks); - if (ecdata.rx) - g_regex_unref (ecdata.rx); + if (ecdata.rx) + g_regex_unref(ecdata.rx); - if (ecdata.n == 0) { - g_printerr ("no matching contacts found\n"); - return MU_ERROR_NO_MATCHES; - } + if (ecdata.n == 0) { + g_printerr("no matching contacts found\n"); + return MU_ERROR_NO_MATCHES; + } - return MU_OK; + return MU_OK; } static gboolean -cfind_params_valid (const MuConfig *opts) +cfind_params_valid(const MuConfig* opts) { - switch (opts->format) { - case MU_CONFIG_FORMAT_PLAIN: - case MU_CONFIG_FORMAT_MUTT_ALIAS: - case MU_CONFIG_FORMAT_MUTT_AB: - case MU_CONFIG_FORMAT_WL: - case MU_CONFIG_FORMAT_BBDB: - case MU_CONFIG_FORMAT_CSV: - case MU_CONFIG_FORMAT_ORG_CONTACT: - case MU_CONFIG_FORMAT_DEBUG: - break; - default: - g_printerr ("invalid output format %s\n", - opts->formatstr ? opts->formatstr : ""); - return FALSE; - } + switch (opts->format) { + case MU_CONFIG_FORMAT_PLAIN: + case MU_CONFIG_FORMAT_MUTT_ALIAS: + case MU_CONFIG_FORMAT_MUTT_AB: + case MU_CONFIG_FORMAT_WL: + case MU_CONFIG_FORMAT_BBDB: + case MU_CONFIG_FORMAT_CSV: + case MU_CONFIG_FORMAT_ORG_CONTACT: + case MU_CONFIG_FORMAT_DEBUG: break; + default: + g_printerr("invalid output format %s\n", + opts->formatstr ? opts->formatstr : ""); + return FALSE; + } - /* only one pattern allowed */ - if (opts->params[1] && opts->params[2]) { - g_printerr ("usage: mu cfind [options] []\n"); - return FALSE; - } + /* only one pattern allowed */ + if (opts->params[1] && opts->params[2]) { + g_printerr("usage: mu cfind [options] []\n"); + return FALSE; + } - return TRUE; + return TRUE; } MuError -Mu::mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts, GError **err) +Mu::mu_cmd_cfind(const Mu::Store& store, const MuConfig* opts, GError** err) { - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_CFIND, MU_ERROR_INTERNAL); - if (!cfind_params_valid (opts)) - throw Mu::Error(Mu::Error::Code::InvalidArgument, - "invalid parameters"); + if (!cfind_params_valid(opts)) + throw Mu::Error(Mu::Error::Code::InvalidArgument, "invalid parameters"); - auto res = run_cmd_cfind (store, - opts->params[1], - opts->personal, - opts->after, - opts->format, - !opts->nocolor, - err); - if (res != MU_OK) - throw Mu::Error(Mu::Error::Code::Internal, err/*consumes*/, - "error in cfind"); - return MU_OK; + auto res = run_cmd_cfind(store, + opts->params[1], + opts->personal, + opts->after, + opts->format, + !opts->nocolor, + err); + if (res != MU_OK) + throw Mu::Error(Mu::Error::Code::Internal, err /*consumes*/, "error in cfind"); + return MU_OK; } diff --git a/mu/mu-cmd-extract.cc b/mu/mu-cmd-extract.cc index 237dd24d..f425b0cf 100644 --- a/mu/mu-cmd-extract.cc +++ b/mu/mu-cmd-extract.cc @@ -32,144 +32,138 @@ using namespace Mu; static gboolean -save_part (MuMsg *msg, const char *targetdir, guint partidx, const MuConfig *opts) +save_part(MuMsg* msg, const char* targetdir, guint partidx, const MuConfig* opts) { - GError *err; - gchar *filepath; - gboolean rv; + GError* err; + gchar* filepath; + gboolean rv; MuMsgOptions msgopts; err = NULL; - rv = FALSE; + rv = FALSE; - msgopts = mu_config_get_msg_options (opts); + msgopts = mu_config_get_msg_options(opts); - filepath = mu_msg_part_get_path (msg, msgopts, targetdir, partidx, &err); + filepath = mu_msg_part_get_path(msg, msgopts, targetdir, partidx, &err); if (!filepath) goto exit; - if (!mu_msg_part_save (msg, msgopts, filepath, partidx, &err)) + if (!mu_msg_part_save(msg, msgopts, filepath, partidx, &err)) goto exit; if (opts->play) - rv = mu_util_play (filepath, TRUE, FALSE, &err); + rv = mu_util_play(filepath, TRUE, FALSE, &err); else rv = TRUE; exit: if (err) { - g_printerr ("error with MIME-part: %s\n", err->message); - g_clear_error (&err); + g_printerr("error with MIME-part: %s\n", err->message); + g_clear_error(&err); } - g_free (filepath); + g_free(filepath); return rv; } - - static gboolean -save_numbered_parts (MuMsg *msg, const MuConfig *opts) +save_numbered_parts(MuMsg* msg, const MuConfig* opts) { gboolean rv; - char **parts, **cur; + char ** parts, **cur; - parts = g_strsplit (opts->parts, ",", 0); + parts = g_strsplit(opts->parts, ",", 0); for (rv = TRUE, cur = parts; cur && *cur; ++cur) { - unsigned idx; - int i; - char *endptr; + int i; + char* endptr; - idx = (unsigned)(i = strtol (*cur, &endptr, 10)); + idx = (unsigned)(i = strtol(*cur, &endptr, 10)); if (i < 0 || *cur == endptr) { - g_printerr ("invalid MIME-part index '%s'\n", *cur); + g_printerr("invalid MIME-part index '%s'\n", *cur); rv = FALSE; break; } - if (!save_part (msg, opts->targetdir, idx, opts)) { - g_printerr ("failed to save MIME-part %d\n", idx); + if (!save_part(msg, opts->targetdir, idx, opts)) { + g_printerr("failed to save MIME-part %d\n", idx); rv = FALSE; break; } } - g_strfreev (parts); + g_strfreev(parts); return rv; } static GRegex* -anchored_regex (const char* pattern) +anchored_regex(const char* pattern) { - GRegex *rx; - GError *err; - gchar *anchored; + GRegex* rx; + GError* err; + gchar* anchored; - - anchored = g_strdup_printf - ("%s%s%s", - pattern[0] == '^' ? "" : "^", - pattern, - pattern[strlen(pattern)-1] == '$' ? "" : "$"); + anchored = g_strdup_printf("%s%s%s", + pattern[0] == '^' ? "" : "^", + pattern, + pattern[strlen(pattern) - 1] == '$' ? "" : "$"); err = NULL; - rx = g_regex_new (anchored, - (GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE), - (GRegexMatchFlags)0, &err); - g_free (anchored); + rx = g_regex_new(anchored, + (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE), + (GRegexMatchFlags)0, + &err); + g_free(anchored); if (!rx) { - g_printerr ("error in regular expression '%s': %s\n", - pattern, err->message ? err->message : "error"); - g_error_free (err); + g_printerr("error in regular expression '%s': %s\n", + pattern, + err->message ? err->message : "error"); + g_error_free(err); return NULL; } return rx; } - static gboolean -save_part_with_filename (MuMsg *msg, const char *pattern, const MuConfig *opts) +save_part_with_filename(MuMsg* msg, const char* pattern, const MuConfig* opts) { - GSList *lst, *cur; - GRegex *rx; - gboolean rv; + GSList * lst, *cur; + GRegex* rx; + gboolean rv; MuMsgOptions msgopts; - msgopts = mu_config_get_msg_options (opts); + msgopts = mu_config_get_msg_options(opts); /* 'anchor' the pattern with '^...$' if not already */ - rx = anchored_regex (pattern); + rx = anchored_regex(pattern); if (!rx) return FALSE; - lst = mu_msg_find_files (msg, msgopts, rx); - g_regex_unref (rx); + lst = mu_msg_find_files(msg, msgopts, rx); + g_regex_unref(rx); if (!lst) { - g_printerr ("no matching attachments found"); + g_printerr("no matching attachments found"); return FALSE; } - for (cur = lst, rv = TRUE; cur; cur = g_slist_next (cur)) - rv = rv && save_part (msg, opts->targetdir, - GPOINTER_TO_UINT(cur->data), opts); - g_slist_free (lst); + for (cur = lst, rv = TRUE; cur; cur = g_slist_next(cur)) + rv = rv && save_part(msg, opts->targetdir, GPOINTER_TO_UINT(cur->data), opts); + g_slist_free(lst); return rv; } struct _SaveData { - gboolean result; - guint saved_num; - const MuConfig *opts; + gboolean result; + guint saved_num; + const MuConfig* opts; }; -typedef struct _SaveData SaveData; - +typedef struct _SaveData SaveData; static gboolean -ignore_part (MuMsg *msg, MuMsgPart *part, SaveData *sd) +ignore_part(MuMsg* msg, MuMsgPart* part, SaveData* sd) { /* something went wrong somewhere; stop */ if (!sd->result) @@ -180,93 +174,86 @@ ignore_part (MuMsg *msg, MuMsgPart *part, SaveData *sd) return TRUE; /* filter out non-attachments? */ - if (!sd->opts->save_all && - !(mu_msg_part_maybe_attachment (part))) + if (!sd->opts->save_all && !(mu_msg_part_maybe_attachment(part))) return TRUE; return FALSE; } - static void -save_part_if (MuMsg *msg, MuMsgPart *part, SaveData *sd) +save_part_if(MuMsg* msg, MuMsgPart* part, SaveData* sd) { - gchar *filepath; - gboolean rv; - GError *err; + gchar* filepath; + gboolean rv; + GError* err; MuMsgOptions msgopts; - if (ignore_part (msg, part, sd)) + if (ignore_part(msg, part, sd)) return; - rv = FALSE; + rv = FALSE; filepath = NULL; err = NULL; - msgopts = mu_config_get_msg_options (sd->opts); - filepath = mu_msg_part_get_path (msg, msgopts, - sd->opts->targetdir, - part->index, &err); + msgopts = mu_config_get_msg_options(sd->opts); + filepath = mu_msg_part_get_path(msg, msgopts, sd->opts->targetdir, part->index, &err); if (!filepath) goto exit; - if (!mu_msg_part_save (msg, msgopts, filepath, part->index, &err)) + if (!mu_msg_part_save(msg, msgopts, filepath, part->index, &err)) goto exit; if (sd->opts->play) - rv = mu_util_play (filepath, TRUE, FALSE, &err); + rv = mu_util_play(filepath, TRUE, FALSE, &err); else rv = TRUE; ++sd->saved_num; exit: if (err) - g_printerr ("error saving MIME part: %s", err->message); + g_printerr("error saving MIME part: %s", err->message); - g_free (filepath); - g_clear_error (&err); + g_free(filepath); + g_clear_error(&err); sd->result = rv; - } static gboolean -save_certain_parts (MuMsg *msg, const MuConfig *opts) +save_certain_parts(MuMsg* msg, const MuConfig* opts) { - SaveData sd; + SaveData sd; MuMsgOptions msgopts; - sd.result = TRUE; - sd.saved_num = 0; - sd.opts = opts; + sd.result = TRUE; + sd.saved_num = 0; + sd.opts = opts; - msgopts = mu_config_get_msg_options (opts); - mu_msg_part_foreach (msg, msgopts, - (MuMsgPartForeachFunc)save_part_if, &sd); + msgopts = mu_config_get_msg_options(opts); + mu_msg_part_foreach(msg, msgopts, (MuMsgPartForeachFunc)save_part_if, &sd); if (sd.saved_num == 0) { - g_printerr ("no %s extracted from this message", - opts->save_attachments ? "attachments" : "parts"); + g_printerr("no %s extracted from this message", + opts->save_attachments ? "attachments" : "parts"); sd.result = FALSE; } return sd.result; } - static gboolean -save_parts (const char *path, const char *filename, const MuConfig *opts) +save_parts(const char* path, const char* filename, const MuConfig* opts) { - MuMsg* msg; + MuMsg* msg; gboolean rv; - GError *err; + GError* err; err = NULL; - msg = mu_msg_new_from_file (path, NULL, &err); + msg = mu_msg_new_from_file(path, NULL, &err); if (!msg) { if (err) { - g_printerr ("error: %s", err->message); - g_error_free (err); + g_printerr("error: %s", err->message); + g_error_free(err); } return FALSE; } @@ -276,21 +263,25 @@ save_parts (const char *path, const char *filename, const MuConfig *opts) /* should we save some explicit parts? */ if (opts->parts) - rv = save_numbered_parts (msg, opts); + rv = save_numbered_parts(msg, opts); else if (filename) - rv = save_part_with_filename (msg, filename, opts); + rv = save_part_with_filename(msg, filename, opts); else - rv = save_certain_parts (msg, opts); + rv = save_certain_parts(msg, opts); - mu_msg_unref (msg); + mu_msg_unref(msg); return rv; } -#define color_maybe(C) do{ if (color) fputs ((C),stdout);}while(0) +#define color_maybe(C) \ + do { \ + if (color) \ + fputs((C), stdout); \ + } while (0) static const char* -disp_str (MuMsgPartType ptype) +disp_str(MuMsgPartType ptype) { if (ptype & MU_MSG_PART_TYPE_ATTACHMENT) return "attach"; @@ -300,94 +291,89 @@ disp_str (MuMsgPartType ptype) } static void -each_part_show (MuMsg *msg, MuMsgPart *part, gboolean color) +each_part_show(MuMsg* msg, MuMsgPart* part, gboolean color) { /* index */ - g_print (" %u ", part->index); + g_print(" %u ", part->index); /* filename */ - color_maybe (MU_COLOR_GREEN); { - gchar *fname; - fname = mu_msg_part_get_filename (part, FALSE); - mu_util_fputs_encoded (fname ? fname : "", stdout); - g_free (fname); + color_maybe(MU_COLOR_GREEN); + { + gchar* fname; + fname = mu_msg_part_get_filename(part, FALSE); + mu_util_fputs_encoded(fname ? fname : "", stdout); + g_free(fname); } /* content-type */ - color_maybe (MU_COLOR_BLUE); - mu_util_print_encoded ( - " %s/%s ", - part->type ? part->type : "", - part->subtype ? part->subtype : ""); + color_maybe(MU_COLOR_BLUE); + mu_util_print_encoded(" %s/%s ", + part->type ? part->type : "", + part->subtype ? part->subtype : ""); /* /\* disposition *\/ */ - color_maybe (MU_COLOR_MAGENTA); - mu_util_print_encoded ("[%s]", disp_str(part->part_type)); + color_maybe(MU_COLOR_MAGENTA); + mu_util_print_encoded("[%s]", disp_str(part->part_type)); /* size */ if (part->size > 0) { - color_maybe (MU_COLOR_CYAN); - g_print (" (%s)", mu_str_size_s (part->size)); + color_maybe(MU_COLOR_CYAN); + g_print(" (%s)", mu_str_size_s(part->size)); } - color_maybe (MU_COLOR_DEFAULT); - fputs ("\n", stdout); + color_maybe(MU_COLOR_DEFAULT); + fputs("\n", stdout); } - static gboolean -show_parts (const char* path, const MuConfig *opts, GError **err) +show_parts(const char* path, const MuConfig* opts, GError** err) { - MuMsg *msg; + MuMsg* msg; MuMsgOptions msgopts; - msg = mu_msg_new_from_file (path, NULL, err); + msg = mu_msg_new_from_file(path, NULL, err); if (!msg) return FALSE; - msgopts = mu_config_get_msg_options (opts); + msgopts = mu_config_get_msg_options(opts); /* TODO: update this for crypto */ - g_print ("MIME-parts in this message:\n"); - mu_msg_part_foreach - (msg, msgopts, - (MuMsgPartForeachFunc)each_part_show, - GUINT_TO_POINTER(!opts->nocolor)); + g_print("MIME-parts in this message:\n"); + mu_msg_part_foreach(msg, + msgopts, + (MuMsgPartForeachFunc)each_part_show, + GUINT_TO_POINTER(!opts->nocolor)); - mu_msg_unref (msg); + mu_msg_unref(msg); return TRUE; - } - static gboolean -check_params (const MuConfig *opts, GError **err) +check_params(const MuConfig* opts, GError** err) { size_t param_num; - param_num = mu_config_param_num (opts); + param_num = mu_config_param_num(opts); if (param_num < 2) { - mu_util_g_set_error - (err, MU_ERROR_IN_PARAMETERS, - "parameters missing"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "parameters missing"); return FALSE; } if (opts->save_attachments || opts->save_all) if (opts->parts || param_num == 3) { - mu_util_g_set_error - (err, MU_ERROR_IN_PARAMETERS, - "--save-attachments and --save-all don't " - "accept a filename pattern or --parts"); + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "--save-attachments and --save-all don't " + "accept a filename pattern or --parts"); return FALSE; } if (opts->save_attachments && opts->save_all) { - mu_util_g_set_error - (err, MU_ERROR_IN_PARAMETERS, - "only one of --save-attachments and" - " --save-all is allowed"); + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "only one of --save-attachments and" + " --save-all is allowed"); return FALSE; } @@ -395,32 +381,28 @@ check_params (const MuConfig *opts, GError **err) } MuError -Mu::mu_cmd_extract (const MuConfig *opts, GError **err) +Mu::mu_cmd_extract(const MuConfig* opts, GError** err) { int rv; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_EXTRACT, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_EXTRACT, MU_ERROR_INTERNAL); - if (!check_params (opts, err)) + if (!check_params(opts, err)) return MU_ERROR_IN_PARAMETERS; - if (!opts->params[2] && !opts->parts && - !opts->save_attachments && !opts->save_all) + if (!opts->params[2] && !opts->parts && !opts->save_attachments && !opts->save_all) /* show, don't save */ - rv = show_parts (opts->params[1], opts, err); + rv = show_parts(opts->params[1], opts, err); else { rv = mu_util_check_dir(opts->targetdir, FALSE, TRUE); if (!rv) - mu_util_g_set_error - (err, MU_ERROR_FILE_CANNOT_WRITE, - "target '%s' is not a writable directory", - opts->targetdir); + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_WRITE, + "target '%s' is not a writable directory", + opts->targetdir); else - rv = save_parts (opts->params[1], - opts->params[2], - opts); /* save */ + rv = save_parts(opts->params[1], opts->params[2], opts); /* save */ } return rv ? MU_OK : MU_ERROR; diff --git a/mu/mu-cmd-find.cc b/mu/mu-cmd-find.cc index b9c1e475..a4039686 100644 --- a/mu/mu-cmd-find.cc +++ b/mu/mu-cmd-find.cc @@ -43,698 +43,688 @@ using namespace Mu; -struct OutputInfo{ - Xapian::docid docid{}; - bool header{}; - bool footer{}; - bool last{}; - Option match_info; +struct OutputInfo { + Xapian::docid docid{}; + bool header{}; + bool footer{}; + bool last{}; + Option match_info; }; constexpr auto FirstOutput{OutputInfo{0, true, false}}; constexpr auto LastOutput{OutputInfo{0, false, true}}; -using OutputFunc = std::function; +using OutputFunc = std::function; static gboolean -print_internal (const Query& query, const std::string& expr, gboolean xapian, - gboolean warn, GError **err) +print_internal(const Query& query, + const std::string& expr, + gboolean xapian, + gboolean warn, + GError** err) { - std::cout << query.parse(expr, xapian) << "\n"; - return TRUE; + std::cout << query.parse(expr, xapian) << "\n"; + return TRUE; } - /* returns MU_MSG_FIELD_ID_NONE if there is an error */ static MuMsgFieldId -sort_field_from_string (const char* fieldstr, GError **err) +sort_field_from_string(const char* fieldstr, GError** err) { - MuMsgFieldId mfid; + MuMsgFieldId mfid; - mfid = mu_msg_field_id_from_name (fieldstr, FALSE); + mfid = mu_msg_field_id_from_name(fieldstr, FALSE); - /* not found? try a shortcut */ - if (mfid == MU_MSG_FIELD_ID_NONE && - strlen(fieldstr) == 1) - mfid = mu_msg_field_id_from_shortcut(fieldstr[0], - FALSE); - if (mfid == MU_MSG_FIELD_ID_NONE) - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, - "not a valid sort field: '%s'\n", fieldstr); - return mfid; + /* not found? try a shortcut */ + if (mfid == MU_MSG_FIELD_ID_NONE && strlen(fieldstr) == 1) + mfid = mu_msg_field_id_from_shortcut(fieldstr[0], FALSE); + if (mfid == MU_MSG_FIELD_ID_NONE) + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_IN_PARAMETERS, + "not a valid sort field: '%s'\n", + fieldstr); + return mfid; } - static Option -run_query (const Query& q, const std::string& expr, const MuConfig *opts, GError **err) +run_query(const Query& q, const std::string& expr, const MuConfig* opts, GError** err) { - MuMsgFieldId sortid; + MuMsgFieldId sortid; - sortid = MU_MSG_FIELD_ID_NONE; - if (opts->sortfield) { - sortid = sort_field_from_string (opts->sortfield, err); - if (sortid == MU_MSG_FIELD_ID_NONE) /* error occurred? */ - return Nothing; - } + sortid = MU_MSG_FIELD_ID_NONE; + if (opts->sortfield) { + sortid = sort_field_from_string(opts->sortfield, err); + if (sortid == MU_MSG_FIELD_ID_NONE) /* error occurred? */ + return Nothing; + } - Mu::QueryFlags qflags{QueryFlags::None}; - if (opts->reverse) - qflags |= QueryFlags::Descending; - if (opts->skip_dups) - qflags |= QueryFlags::SkipDuplicates; - if (opts->include_related) - qflags |= QueryFlags::IncludeRelated; - if (opts->threads) - qflags |= QueryFlags::Threading; + Mu::QueryFlags qflags{QueryFlags::None}; + if (opts->reverse) + qflags |= QueryFlags::Descending; + if (opts->skip_dups) + qflags |= QueryFlags::SkipDuplicates; + if (opts->include_related) + qflags |= QueryFlags::IncludeRelated; + if (opts->threads) + qflags |= QueryFlags::Threading; - return q.run(expr, sortid, qflags, opts->maxnum); + return q.run(expr, sortid, qflags, opts->maxnum); } static gboolean -exec_cmd (MuMsg *msg, const OutputInfo& info, - const MuConfig *opts, GError **err) +exec_cmd(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) { - gint status; - char *cmdline, *escpath; - gboolean rv; + gint status; + char * cmdline, *escpath; + gboolean rv; - escpath = g_shell_quote (mu_msg_get_path (msg)); - cmdline = g_strdup_printf ("%s %s", opts->exec, escpath); + escpath = g_shell_quote(mu_msg_get_path(msg)); + cmdline = g_strdup_printf("%s %s", opts->exec, escpath); - rv = g_spawn_command_line_sync (cmdline, NULL, NULL, &status, err); + rv = g_spawn_command_line_sync(cmdline, NULL, NULL, &status, err); - g_free (cmdline); - g_free (escpath); + g_free(cmdline); + g_free(escpath); - return rv; + return rv; } static gchar* -resolve_bookmark (const MuConfig *opts, GError **err) +resolve_bookmark(const MuConfig* opts, GError** err) { - MuBookmarks *bm; - char* val; - const gchar *bmfile; + MuBookmarks* bm; + char* val; + const gchar* bmfile; - bmfile = mu_runtime_path (MU_RUNTIME_PATH_BOOKMARKS); - bm = mu_bookmarks_new (bmfile); - if (!bm) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN, - "failed to open bookmarks file '%s'", bmfile); - return FALSE; - } + bmfile = mu_runtime_path(MU_RUNTIME_PATH_BOOKMARKS); + bm = mu_bookmarks_new(bmfile); + if (!bm) { + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_FILE_CANNOT_OPEN, + "failed to open bookmarks file '%s'", + bmfile); + return FALSE; + } - val = (gchar*)mu_bookmarks_lookup (bm, opts->bookmark); - if (!val) - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_NO_MATCHES, - "bookmark '%s' not found", opts->bookmark); - else - val = g_strdup (val); + val = (gchar*)mu_bookmarks_lookup(bm, opts->bookmark); + if (!val) + g_set_error(err, + MU_ERROR_DOMAIN, + MU_ERROR_NO_MATCHES, + "bookmark '%s' not found", + opts->bookmark); + else + val = g_strdup(val); - mu_bookmarks_destroy (bm); - return val; + mu_bookmarks_destroy(bm); + return val; } static Option -get_query (const MuConfig *opts, GError **err) +get_query(const MuConfig* opts, GError** err) { - gchar *query, *bookmarkval; + gchar *query, *bookmarkval; - /* params[0] is 'find', actual search params start with [1] */ - if (!opts->bookmark && !opts->params[1]) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, - "error in parameters"); - return Nothing; - } + /* params[0] is 'find', actual search params start with [1] */ + if (!opts->bookmark && !opts->params[1]) { + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, "error in parameters"); + return Nothing; + } - bookmarkval = NULL; - if (opts->bookmark) { - bookmarkval = resolve_bookmark (opts, err); - if (!bookmarkval) - return Nothing; - } + bookmarkval = NULL; + if (opts->bookmark) { + bookmarkval = resolve_bookmark(opts, err); + if (!bookmarkval) + return Nothing; + } - query = g_strjoinv (" ", &opts->params[1]); - if (bookmarkval) { - gchar *tmp; - tmp = g_strdup_printf ("%s %s", bookmarkval, query); - g_free (query); - query = tmp; - } + query = g_strjoinv(" ", &opts->params[1]); + if (bookmarkval) { + gchar* tmp; + tmp = g_strdup_printf("%s %s", bookmarkval, query); + g_free(query); + query = tmp; + } - g_free (bookmarkval); + g_free(bookmarkval); - std::string q{query}; - g_free(query); + std::string q{query}; + g_free(query); - return q; + return q; } static Mu::Query -get_query_obj (const Store& store, GError **err) +get_query_obj(const Store& store, GError** err) { - const auto count{store.size()}; + const auto count{store.size()}; - if (count == (unsigned)-1) - throw Mu::Error(Error::Code::Store, "invalid store"); + if (count == (unsigned)-1) + throw Mu::Error(Error::Code::Store, "invalid store"); - if (count == 0) - throw Mu::Error(Error::Code::Store, "store is empty"); + if (count == 0) + throw Mu::Error(Error::Code::Store, "store is empty"); - return Mu::Query{store}; + return Mu::Query{store}; } static gboolean -prepare_links (const MuConfig *opts, GError **err) +prepare_links(const MuConfig* opts, GError** err) { - /* note, mu_maildir_mkdir simply ignores whatever part of the - * mail dir already exists */ + /* note, mu_maildir_mkdir simply ignores whatever part of the + * mail dir already exists */ - if (!mu_maildir_mkdir (opts->linksdir, 0700, TRUE, err)) { - mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_MKDIR, - "error creating %s", opts->linksdir); - return FALSE; - } + if (!mu_maildir_mkdir(opts->linksdir, 0700, TRUE, err)) { + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_MKDIR, + "error creating %s", + opts->linksdir); + return FALSE; + } - if (opts->clearlinks && - !mu_maildir_clear_links (opts->linksdir, err)) { - mu_util_g_set_error (err, MU_ERROR_FILE, - "error clearing links under %s", - opts->linksdir); - return FALSE; - } + if (opts->clearlinks && !mu_maildir_clear_links(opts->linksdir, err)) { + mu_util_g_set_error(err, + MU_ERROR_FILE, + "error clearing links under %s", + opts->linksdir); + return FALSE; + } - return TRUE; + return TRUE; } static bool -output_link (MuMsg *msg, const OutputInfo& info, - const MuConfig *opts, GError **err) +output_link(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) { - if (info.header) - return prepare_links (opts, err); - else if (info.footer) - return true; + if (info.header) + return prepare_links(opts, err); + else if (info.footer) + return true; - return mu_maildir_link (mu_msg_get_path (msg), - opts->linksdir, err); + return mu_maildir_link(mu_msg_get_path(msg), opts->linksdir, err); } static void -ansi_color_maybe (MuMsgFieldId mfid, gboolean color) +ansi_color_maybe(MuMsgFieldId mfid, gboolean color) { - const char* ansi; + const char* ansi; - if (!color) - return; /* nothing to do */ + if (!color) + return; /* nothing to do */ - switch (mfid) { + switch (mfid) { + case MU_MSG_FIELD_ID_FROM: ansi = MU_COLOR_CYAN; break; - case MU_MSG_FIELD_ID_FROM: - ansi = MU_COLOR_CYAN; break; + case MU_MSG_FIELD_ID_TO: + case MU_MSG_FIELD_ID_CC: + case MU_MSG_FIELD_ID_BCC: ansi = MU_COLOR_BLUE; break; - case MU_MSG_FIELD_ID_TO: - case MU_MSG_FIELD_ID_CC: - case MU_MSG_FIELD_ID_BCC: - ansi = MU_COLOR_BLUE; break; + case MU_MSG_FIELD_ID_SUBJECT: ansi = MU_COLOR_GREEN; break; - case MU_MSG_FIELD_ID_SUBJECT: - ansi = MU_COLOR_GREEN; break; + case MU_MSG_FIELD_ID_DATE: ansi = MU_COLOR_MAGENTA; break; - case MU_MSG_FIELD_ID_DATE: - ansi = MU_COLOR_MAGENTA; break; + default: + if (mu_msg_field_type(mfid) == MU_MSG_FIELD_TYPE_STRING) + ansi = MU_COLOR_YELLOW; + else + ansi = MU_COLOR_RED; + } - default: - if (mu_msg_field_type(mfid) == MU_MSG_FIELD_TYPE_STRING) - ansi = MU_COLOR_YELLOW; - else - ansi = MU_COLOR_RED; - } - - fputs (ansi, stdout); + fputs(ansi, stdout); } static void -ansi_reset_maybe (MuMsgFieldId mfid, gboolean color) +ansi_reset_maybe(MuMsgFieldId mfid, gboolean color) { - if (!color) - return; /* nothing to do */ - - fputs (MU_COLOR_DEFAULT, stdout); + if (!color) + return; /* nothing to do */ + fputs(MU_COLOR_DEFAULT, stdout); } static const char* -field_string_list (MuMsg *msg, MuMsgFieldId mfid) +field_string_list(MuMsg* msg, MuMsgFieldId mfid) { - char *str; - const GSList *lst; - static char buf[80]; + char* str; + const GSList* lst; + static char buf[80]; - lst = mu_msg_get_field_string_list (msg, mfid); - if (!lst) - return NULL; + lst = mu_msg_get_field_string_list(msg, mfid); + if (!lst) + return NULL; - str = mu_str_from_list (lst, ','); - if (str) { - strncpy (buf, str, sizeof(buf)-1); - buf[sizeof(buf)-1]='\0'; - g_free (str); - return buf; - } + str = mu_str_from_list(lst, ','); + if (str) { + strncpy(buf, str, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + g_free(str); + return buf; + } - return NULL; + return NULL; } static const char* -display_field (MuMsg *msg, MuMsgFieldId mfid) +display_field(MuMsg* msg, MuMsgFieldId mfid) { - gint64 val; + gint64 val; - switch (mu_msg_field_type(mfid)) { - case MU_MSG_FIELD_TYPE_STRING: { - const gchar *str; - str = mu_msg_get_field_string (msg, mfid); - return str ? str : ""; - } - case MU_MSG_FIELD_TYPE_INT: + switch (mu_msg_field_type(mfid)) { + case MU_MSG_FIELD_TYPE_STRING: { + const gchar* str; + str = mu_msg_get_field_string(msg, mfid); + return str ? str : ""; + } + case MU_MSG_FIELD_TYPE_INT: - if (mfid == MU_MSG_FIELD_ID_PRIO) { - val = mu_msg_get_field_numeric (msg, mfid); - return mu_msg_prio_name ((MuMsgPrio)val); - } else if (mfid == MU_MSG_FIELD_ID_FLAGS) { - val = mu_msg_get_field_numeric (msg, mfid); - return mu_str_flags_s ((MuFlags)val); - } else /* as string */ - return mu_msg_get_field_string (msg, mfid); + if (mfid == MU_MSG_FIELD_ID_PRIO) { + val = mu_msg_get_field_numeric(msg, mfid); + return mu_msg_prio_name((MuMsgPrio)val); + } else if (mfid == MU_MSG_FIELD_ID_FLAGS) { + val = mu_msg_get_field_numeric(msg, mfid); + return mu_str_flags_s((MuFlags)val); + } else /* as string */ + return mu_msg_get_field_string(msg, mfid); - case MU_MSG_FIELD_TYPE_TIME_T: - val = mu_msg_get_field_numeric (msg, mfid); - return mu_date_str_s ("%c", (time_t)val); + case MU_MSG_FIELD_TYPE_TIME_T: + val = mu_msg_get_field_numeric(msg, mfid); + return mu_date_str_s("%c", (time_t)val); - case MU_MSG_FIELD_TYPE_BYTESIZE: - val = mu_msg_get_field_numeric (msg, mfid); - return mu_str_size_s ((unsigned)val); - case MU_MSG_FIELD_TYPE_STRING_LIST: { - const char *str; - str = field_string_list (msg, mfid); - return str ? str : ""; - } - default: - g_return_val_if_reached (NULL); - } + case MU_MSG_FIELD_TYPE_BYTESIZE: + val = mu_msg_get_field_numeric(msg, mfid); + return mu_str_size_s((unsigned)val); + case MU_MSG_FIELD_TYPE_STRING_LIST: { + const char* str; + str = field_string_list(msg, mfid); + return str ? str : ""; + } + default: g_return_val_if_reached(NULL); + } } static void -print_summary (MuMsg *msg, const MuConfig *opts) +print_summary(MuMsg* msg, const MuConfig* opts) { - const char* body; - char *summ; - MuMsgOptions msgopts; + const char* body; + char* summ; + MuMsgOptions msgopts; - msgopts = mu_config_get_msg_options (opts); - body = mu_msg_get_body_text(msg, msgopts); + msgopts = mu_config_get_msg_options(opts); + body = mu_msg_get_body_text(msg, msgopts); - if (body) - summ = mu_str_summarize (body, (unsigned)opts->summary_len); - else - summ = NULL; + if (body) + summ = mu_str_summarize(body, (unsigned)opts->summary_len); + else + summ = NULL; - g_print ("Summary: "); - mu_util_fputs_encoded (summ ? summ : "", stdout); - g_print ("\n"); + g_print("Summary: "); + mu_util_fputs_encoded(summ ? summ : "", stdout); + g_print("\n"); - g_free (summ); + g_free(summ); } static void -thread_indent (const QueryMatch& info, const MuConfig *opts) +thread_indent(const QueryMatch& info, const MuConfig* opts) { - const auto is_root{any_of(info.flags & QueryMatch::Flags::Root)}; - const auto first_child{any_of(info.flags & QueryMatch::Flags::First)}; - const auto last_child{any_of(info.flags & QueryMatch::Flags::Last)}; - const auto empty_parent{any_of(info.flags & QueryMatch::Flags::Orphan)}; - const auto is_dup{any_of(info.flags & QueryMatch::Flags::Duplicate)}; - //const auto is_related{any_of(info.flags & QueryMatch::Flags::Related)}; + const auto is_root{any_of(info.flags & QueryMatch::Flags::Root)}; + const auto first_child{any_of(info.flags & QueryMatch::Flags::First)}; + const auto last_child{any_of(info.flags & QueryMatch::Flags::Last)}; + const auto empty_parent{any_of(info.flags & QueryMatch::Flags::Orphan)}; + const auto is_dup{any_of(info.flags & QueryMatch::Flags::Duplicate)}; + // const auto is_related{any_of(info.flags & QueryMatch::Flags::Related)}; - /* indent */ - if (opts->debug) { - ::fputs (info.thread_path.c_str(), stdout); - ::fputs (" ", stdout); - } else - for (auto i = info.thread_level; i > 1; --i) - ::fputs (" ", stdout); + /* indent */ + if (opts->debug) { + ::fputs(info.thread_path.c_str(), stdout); + ::fputs(" ", stdout); + } else + for (auto i = info.thread_level; i > 1; --i) + ::fputs(" ", stdout); - if (!is_root) { - if (first_child) - ::fputs ("\\", stdout); - else if (last_child) - ::fputs ("/", stdout); - else - ::fputs (" ", stdout); - ::fputs (empty_parent ? "*> " : is_dup ? "=> " : "-> ", stdout); - } + if (!is_root) { + if (first_child) + ::fputs("\\", stdout); + else if (last_child) + ::fputs("/", stdout); + else + ::fputs(" ", stdout); + ::fputs(empty_parent ? "*> " : is_dup ? "=> " : "-> ", stdout); + } } static void -output_plain_fields (MuMsg *msg, const char *fields, - gboolean color, gboolean threads) +output_plain_fields(MuMsg* msg, const char* fields, gboolean color, gboolean threads) { - const char* myfields; - int nonempty; + const char* myfields; + int nonempty; - g_return_if_fail (fields); + g_return_if_fail(fields); - for (myfields = fields, nonempty = 0; *myfields; ++myfields) { + for (myfields = fields, nonempty = 0; *myfields; ++myfields) { + MuMsgFieldId mfid; + mfid = mu_msg_field_id_from_shortcut(*myfields, FALSE); - MuMsgFieldId mfid; - mfid = mu_msg_field_id_from_shortcut (*myfields, FALSE); + if (mfid == MU_MSG_FIELD_ID_NONE || + (!mu_msg_field_xapian_value(mfid) && !mu_msg_field_xapian_contact(mfid))) + nonempty += printf("%c", *myfields); - if (mfid == MU_MSG_FIELD_ID_NONE || - (!mu_msg_field_xapian_value (mfid) && - !mu_msg_field_xapian_contact (mfid))) - nonempty += printf ("%c", *myfields); + else { + ansi_color_maybe(mfid, color); + nonempty += mu_util_fputs_encoded(display_field(msg, mfid), stdout); + ansi_reset_maybe(mfid, color); + } + } - else { - ansi_color_maybe (mfid, color); - nonempty += mu_util_fputs_encoded - (display_field (msg, mfid), stdout); - ansi_reset_maybe (mfid, color); - } - } - - if (nonempty) - fputs ("\n", stdout); + if (nonempty) + fputs("\n", stdout); } static gboolean -output_plain (MuMsg *msg, const OutputInfo& info, const MuConfig *opts, GError **err) +output_plain(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) { - if (!msg) - return true; + if (!msg) + return true; - /* we reuse the color (whatever that may be) - * for message-priority for threads, too */ - ansi_color_maybe (MU_MSG_FIELD_ID_PRIO, !opts->nocolor); - if (opts->threads && info.match_info) - thread_indent (*info.match_info, opts); + /* we reuse the color (whatever that may be) + * for message-priority for threads, too */ + ansi_color_maybe(MU_MSG_FIELD_ID_PRIO, !opts->nocolor); + if (opts->threads && info.match_info) + thread_indent(*info.match_info, opts); - output_plain_fields (msg, opts->fields, !opts->nocolor, opts->threads); + output_plain_fields(msg, opts->fields, !opts->nocolor, opts->threads); - if (opts->summary_len > 0) - print_summary (msg, opts); + if (opts->summary_len > 0) + print_summary(msg, opts); - return TRUE; + return TRUE; } - G_GNUC_UNUSED static std::string -to_string (const Mu::Sexp& sexp, bool color, size_t level = 0) +to_string(const Mu::Sexp& sexp, bool color, size_t level = 0) { - Mu::MaybeAnsi col{color}; - using Color = Mu::MaybeAnsi::Color; + Mu::MaybeAnsi col{color}; + using Color = Mu::MaybeAnsi::Color; - // clang/libc++ don't allow constexpr here - const std::array rainbow = { - Color::BrightBlue, Color::Green, Color::Yellow, - Color::Magenta, Color::Cyan, Color::BrightGreen, - }; + // clang/libc++ don't allow constexpr here + const std::array rainbow = { + Color::BrightBlue, + Color::Green, + Color::Yellow, + Color::Magenta, + Color::Cyan, + Color::BrightGreen, + }; - std::stringstream sstrm; + std::stringstream sstrm; - switch (sexp.type()) { - case Sexp::Type::List: { - const auto bracecol{col.fg(rainbow[level % rainbow.size()])}; - sstrm << bracecol << "("; + switch (sexp.type()) { + case Sexp::Type::List: { + const auto bracecol{col.fg(rainbow[level % rainbow.size()])}; + sstrm << bracecol << "("; - bool first{true}; - for (auto&& child : sexp.list()) { - sstrm << (first ? "" : " ") - << to_string(child , color, level + 1); - first = false; - } - sstrm << bracecol << ")"; - break; - } - case Sexp::Type::String: - sstrm << col.fg(Color::BrightCyan) << Mu::quote(sexp.value()) - << col.reset(); - break; - case Sexp::Type::Number: - sstrm << col.fg(Color::BrightMagenta) << sexp.value() - << col.reset(); - break; - case Sexp::Type::Symbol: - sstrm << (col.fg(sexp.value().at(0) == ':' ? Color::BrightGreen : Color::BrightBlue)) - << sexp.value() << col.reset(); - break; - default: - throw std::logic_error ("invalid type"); - } + bool first{true}; + for (auto&& child : sexp.list()) { + sstrm << (first ? "" : " ") << to_string(child, color, level + 1); + first = false; + } + sstrm << bracecol << ")"; + break; + } + case Sexp::Type::String: + sstrm << col.fg(Color::BrightCyan) << Mu::quote(sexp.value()) << col.reset(); + break; + case Sexp::Type::Number: + sstrm << col.fg(Color::BrightMagenta) << sexp.value() << col.reset(); + break; + case Sexp::Type::Symbol: + sstrm << (col.fg(sexp.value().at(0) == ':' ? Color::BrightGreen + : Color::BrightBlue)) + << sexp.value() << col.reset(); + break; + default: throw std::logic_error("invalid type"); + } - return sstrm.str(); -} - - -static bool -output_sexp (MuMsg *msg, const OutputInfo& info, const MuConfig *opts, GError **err) -{ - if (!msg) - return true; - - fputs(msg_to_sexp(msg, 0, MU_MSG_OPTION_HEADERS_ONLY) - .to_sexp_string().c_str(), stdout); - fputs ("\n", stdout); - - return true; + return sstrm.str(); } static bool -output_json (MuMsg *msg, const OutputInfo& info, const MuConfig *opts, GError **err) +output_sexp(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) { - if (info.header) { - g_print ("[\n"); - return true; - } + if (!msg) + return true; - if (info.footer) { - g_print("]\n"); - return true; - } + fputs(msg_to_sexp(msg, 0, MU_MSG_OPTION_HEADERS_ONLY).to_sexp_string().c_str(), stdout); + fputs("\n", stdout); - g_print("%s%s\n", msg_to_sexp(msg, info.docid, MU_MSG_OPTION_HEADERS_ONLY) - .to_json_string().c_str(), info.last ? "" : ","); + return true; +} - return true; +static bool +output_json(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) +{ + if (info.header) { + g_print("[\n"); + return true; + } + + if (info.footer) { + g_print("]\n"); + return true; + } + + g_print("%s%s\n", + msg_to_sexp(msg, info.docid, MU_MSG_OPTION_HEADERS_ONLY).to_json_string().c_str(), + info.last ? "" : ","); + + return true; } static void -print_attr_xml (const char* elm, const char *str) +print_attr_xml(const char* elm, const char* str) { - gchar *esc; + gchar* esc; - if (mu_str_is_empty(str)) - return; /* empty: don't include */ + if (mu_str_is_empty(str)) + return; /* empty: don't include */ - esc = g_markup_escape_text (str, -1); - g_print ("\t\t<%s>%s\n", elm, esc, elm); - g_free (esc); + esc = g_markup_escape_text(str, -1); + g_print("\t\t<%s>%s\n", elm, esc, elm); + g_free(esc); } static bool -output_xml (MuMsg *msg, const OutputInfo& info, const MuConfig *opts, GError **err) +output_xml(MuMsg* msg, const OutputInfo& info, const MuConfig* opts, GError** err) { - if (info.header) { - g_print ("\n"); - g_print ("\n"); - return true; - } + if (info.header) { + g_print("\n"); + g_print("\n"); + return true; + } - if (info.footer) { - g_print ("\n"); - return true; - } + if (info.footer) { + g_print("\n"); + return true; + } - g_print ("\t\n"); - print_attr_xml ("from", mu_msg_get_from (msg)); - print_attr_xml ("to", mu_msg_get_to (msg)); - print_attr_xml ("cc", mu_msg_get_cc (msg)); - print_attr_xml ("subject", mu_msg_get_subject (msg)); - g_print ("\t\t%u\n", - (unsigned)mu_msg_get_date (msg)); - g_print ("\t\t%u\n", (unsigned)mu_msg_get_size (msg)); - print_attr_xml ("msgid", mu_msg_get_msgid (msg)); - print_attr_xml ("path", mu_msg_get_path (msg)); - print_attr_xml ("maildir", mu_msg_get_maildir (msg)); - g_print ("\t\n"); + g_print("\t\n"); + print_attr_xml("from", mu_msg_get_from(msg)); + print_attr_xml("to", mu_msg_get_to(msg)); + print_attr_xml("cc", mu_msg_get_cc(msg)); + print_attr_xml("subject", mu_msg_get_subject(msg)); + g_print("\t\t%u\n", (unsigned)mu_msg_get_date(msg)); + g_print("\t\t%u\n", (unsigned)mu_msg_get_size(msg)); + print_attr_xml("msgid", mu_msg_get_msgid(msg)); + print_attr_xml("path", mu_msg_get_path(msg)); + print_attr_xml("maildir", mu_msg_get_maildir(msg)); + g_print("\t\n"); - return true; + return true; } static OutputFunc -get_output_func (const MuConfig *opts, GError **err) +get_output_func(const MuConfig* opts, GError** err) { - switch (opts->format) { - case MU_CONFIG_FORMAT_LINKS: return output_link; - case MU_CONFIG_FORMAT_EXEC: return exec_cmd; - case MU_CONFIG_FORMAT_PLAIN: return output_plain; - case MU_CONFIG_FORMAT_XML: return output_xml; - case MU_CONFIG_FORMAT_SEXP: return output_sexp; - case MU_CONFIG_FORMAT_JSON: return output_json; + switch (opts->format) { + case MU_CONFIG_FORMAT_LINKS: return output_link; + case MU_CONFIG_FORMAT_EXEC: return exec_cmd; + case MU_CONFIG_FORMAT_PLAIN: return output_plain; + case MU_CONFIG_FORMAT_XML: return output_xml; + case MU_CONFIG_FORMAT_SEXP: return output_sexp; + case MU_CONFIG_FORMAT_JSON: return output_json; - default: - g_return_val_if_reached (NULL); - return NULL; - } + default: g_return_val_if_reached(NULL); return NULL; + } } static bool -output_query_results (const QueryResults& qres, const MuConfig *opts, GError **err) +output_query_results(const QueryResults& qres, const MuConfig* opts, GError** err) { - const auto output_func{get_output_func (opts, err)}; - if (!output_func) - return false; + const auto output_func{get_output_func(opts, err)}; + if (!output_func) + return false; - gboolean rv{true}; - output_func (NULL, FirstOutput, opts, NULL); + gboolean rv{true}; + output_func(NULL, FirstOutput, opts, NULL); size_t n{0}; - for (auto&& item: qres) { - + for (auto&& item : qres) { n++; - auto msg{item.floating_msg()}; - if (!msg) - continue; + auto msg{item.floating_msg()}; + if (!msg) + continue; - if (opts->after != 0 && mu_msg_get_timestamp(msg) < opts->after) - continue; + if (opts->after != 0 && mu_msg_get_timestamp(msg) < opts->after) + continue; - rv = output_func (msg, {item.doc_id(), false, false, - n == qres.size(), /* last? */ - item.query_match()}, - opts, err); - if (!rv) - break; - } - output_func (NULL, LastOutput, opts, NULL); + rv = output_func(msg, + {item.doc_id(), + false, + false, + n == qres.size(), /* last? */ + item.query_match()}, + opts, + err); + if (!rv) + break; + } + output_func(NULL, LastOutput, opts, NULL); - return rv; + return rv; } static gboolean -process_query (const Query& q, const std::string& expr, const MuConfig *opts, GError **err) +process_query(const Query& q, const std::string& expr, const MuConfig* opts, GError** err) { - auto qres{run_query (q, expr, opts, err)}; - if (!qres) - return FALSE; + auto qres{run_query(q, expr, opts, err)}; + if (!qres) + return FALSE; - if (qres->empty()) { - mu_util_g_set_error (err, MU_ERROR_NO_MATCHES, - "no matches for search expression"); - return false; - } + if (qres->empty()) { + mu_util_g_set_error(err, MU_ERROR_NO_MATCHES, "no matches for search expression"); + return false; + } - return output_query_results (*qres, opts, err); + return output_query_results(*qres, opts, err); } static gboolean -execute_find (const Store& store, const MuConfig *opts, GError **err) +execute_find(const Store& store, const MuConfig* opts, GError** err) { - auto q{get_query_obj (store, err)}; - auto expr{get_query (opts, err)}; - if (!expr) - return FALSE; + auto q{get_query_obj(store, err)}; + auto expr{get_query(opts, err)}; + if (!expr) + return FALSE; - if (opts->format == MU_CONFIG_FORMAT_XQUERY) - return print_internal (q, *expr, TRUE, FALSE, err); - else if (opts->format == MU_CONFIG_FORMAT_MQUERY) - return print_internal (q, *expr, FALSE, - opts->verbose, err); - else - return process_query (q, *expr, opts, err); + if (opts->format == MU_CONFIG_FORMAT_XQUERY) + return print_internal(q, *expr, TRUE, FALSE, err); + else if (opts->format == MU_CONFIG_FORMAT_MQUERY) + return print_internal(q, *expr, FALSE, opts->verbose, err); + else + return process_query(q, *expr, opts, err); } static gboolean -format_params_valid (const MuConfig *opts, GError **err) +format_params_valid(const MuConfig* opts, GError** err) { - switch (opts->format) { - case MU_CONFIG_FORMAT_EXEC: - break; - case MU_CONFIG_FORMAT_PLAIN: - case MU_CONFIG_FORMAT_SEXP: - case MU_CONFIG_FORMAT_JSON: - case MU_CONFIG_FORMAT_LINKS: - case MU_CONFIG_FORMAT_XML: - case MU_CONFIG_FORMAT_XQUERY: - case MU_CONFIG_FORMAT_MQUERY: - if (opts->exec) { - mu_util_g_set_error - (err, MU_ERROR_IN_PARAMETERS, - "--exec and --format cannot be combined"); - return FALSE; - } - break; - default: mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "invalid output format %s", - opts->formatstr ? opts->formatstr : ""); - return FALSE; - } + switch (opts->format) { + case MU_CONFIG_FORMAT_EXEC: break; + case MU_CONFIG_FORMAT_PLAIN: + case MU_CONFIG_FORMAT_SEXP: + case MU_CONFIG_FORMAT_JSON: + case MU_CONFIG_FORMAT_LINKS: + case MU_CONFIG_FORMAT_XML: + case MU_CONFIG_FORMAT_XQUERY: + case MU_CONFIG_FORMAT_MQUERY: + if (opts->exec) { + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "--exec and --format cannot be combined"); + return FALSE; + } + break; + default: + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "invalid output format %s", + opts->formatstr ? opts->formatstr : ""); + return FALSE; + } - if (opts->format == MU_CONFIG_FORMAT_LINKS && !opts->linksdir) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing --linksdir argument"); - return FALSE; - } + if (opts->format == MU_CONFIG_FORMAT_LINKS && !opts->linksdir) { + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing --linksdir argument"); + return FALSE; + } - if (opts->linksdir && opts->format != MU_CONFIG_FORMAT_LINKS) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "--linksdir is only valid with --format=links"); - return FALSE; - } + if (opts->linksdir && opts->format != MU_CONFIG_FORMAT_LINKS) { + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "--linksdir is only valid with --format=links"); + return FALSE; + } - return TRUE; + return TRUE; } static gboolean -query_params_valid (const MuConfig *opts, GError **err) +query_params_valid(const MuConfig* opts, GError** err) { - const gchar *xpath; + const gchar* xpath; - if (!opts->params[1]) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing query"); - return FALSE; - } + if (!opts->params[1]) { + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing query"); + return FALSE; + } - xpath = mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB); - if (mu_util_check_dir (xpath, TRUE, FALSE)) - return TRUE; + xpath = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB); + if (mu_util_check_dir(xpath, TRUE, FALSE)) + return TRUE; - mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_READ, - "'%s' is not a readable Xapian directory", - xpath); - return FALSE; + mu_util_g_set_error(err, + MU_ERROR_FILE_CANNOT_READ, + "'%s' is not a readable Xapian directory", + xpath); + return FALSE; } MuError -Mu::mu_cmd_find (const Store& store, const MuConfig *opts, GError **err) +Mu::mu_cmd_find(const Store& store, const MuConfig* opts, GError** err) { - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_FIND, MU_ERROR_INTERNAL); - MuConfig myopts{*opts}; + MuConfig myopts{*opts}; - if (myopts.exec) - myopts.format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */ + if (myopts.exec) + myopts.format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */ - if (!query_params_valid (&myopts, err) || - !format_params_valid(&myopts, err)) - return MU_G_ERROR_CODE (err); + if (!query_params_valid(&myopts, err) || !format_params_valid(&myopts, err)) + return MU_G_ERROR_CODE(err); - if (!execute_find (store, &myopts, err)) - return MU_G_ERROR_CODE(err); - else - return MU_OK; + if (!execute_find(store, &myopts, err)) + return MU_G_ERROR_CODE(err); + else + return MU_OK; } diff --git a/mu/mu-cmd-index.cc b/mu/mu-cmd-index.cc index 49429fe0..8c262652 100644 --- a/mu/mu-cmd-index.cc +++ b/mu/mu-cmd-index.cc @@ -42,111 +42,107 @@ using namespace Mu; static std::atomic CaughtSignal{}; static void -install_sig_handler (void) +install_sig_handler(void) { struct sigaction action; - int i, sigs[] = { SIGINT, SIGHUP, SIGTERM }; + int i, sigs[] = {SIGINT, SIGHUP, SIGTERM}; sigemptyset(&action.sa_mask); action.sa_flags = SA_RESETHAND; - action.sa_handler = [](int sig) { - if (!CaughtSignal && sig == SIGINT) /* Ctrl-C */ - g_print ("\nshutting down gracefully, " - "press again to kill immediately"); - CaughtSignal = true; - }; + action.sa_handler = [](int sig) { + if (!CaughtSignal && sig == SIGINT) /* Ctrl-C */ + g_print("\nshutting down gracefully, " + "press again to kill immediately"); + CaughtSignal = true; + }; for (i = 0; i != G_N_ELEMENTS(sigs); ++i) - if (sigaction (sigs[i], &action, NULL) != 0) - g_critical ("set sigaction for %d failed: %s", - sigs[i], g_strerror (errno));; + if (sigaction(sigs[i], &action, NULL) != 0) + g_critical("set sigaction for %d failed: %s", sigs[i], g_strerror(errno)); + ; } - static void -print_stats (const Indexer::Progress& stats, bool color) +print_stats(const Indexer::Progress& stats, bool color) { - const char *kars = "-\\|/"; - static auto i = 0U; + const char* kars = "-\\|/"; + static auto i = 0U; - MaybeAnsi col{color}; - using Color = MaybeAnsi::Color; + MaybeAnsi col{color}; + using Color = MaybeAnsi::Color; - std::cout << col.fg(Color::Yellow) << kars[++i % 4] << col.reset() - << " indexing messages; " - << "processed: " << col.fg(Color::Green) << stats.processed << col.reset() - << "; updated/new: " << col.fg(Color::Green) << stats.updated << col.reset() - << "; cleaned-up: " << col.fg(Color::Green) << stats.removed << col.reset(); + std::cout << col.fg(Color::Yellow) << kars[++i % 4] << col.reset() << " indexing messages; " + << "processed: " << col.fg(Color::Green) << stats.processed << col.reset() + << "; updated/new: " << col.fg(Color::Green) << stats.updated << col.reset() + << "; cleaned-up: " << col.fg(Color::Green) << stats.removed << col.reset(); } - MuError -Mu::mu_cmd_index (Mu::Store& store, const MuConfig *opts, GError **err) +Mu::mu_cmd_index(Mu::Store& store, const MuConfig* opts, GError** err) { - g_return_val_if_fail (opts, MU_ERROR); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR); + g_return_val_if_fail(opts, MU_ERROR); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR); - /* param[0] == 'index' there should be no param[1] */ + /* param[0] == 'index' there should be no param[1] */ if (opts->params[1]) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "unexpected parameter"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "unexpected parameter"); return MU_ERROR; } if (opts->max_msg_size < 0) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "the maximum message size must be >= 0"); + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "the maximum message size must be >= 0"); return MU_ERROR; } - const auto mdir{store.metadata().root_maildir}; - if (G_UNLIKELY(access (mdir.c_str(), R_OK) != 0)) { - mu_util_g_set_error(err, MU_ERROR_FILE, - "'%s' is not readable: %s", mdir.c_str(), g_strerror (errno)); - return MU_ERROR; - } + const auto mdir{store.metadata().root_maildir}; + if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) { + mu_util_g_set_error(err, + MU_ERROR_FILE, + "'%s' is not readable: %s", + mdir.c_str(), + g_strerror(errno)); + return MU_ERROR; + } - MaybeAnsi col{!opts->nocolor}; - using Color = MaybeAnsi::Color; - if (!opts->quiet) { + MaybeAnsi col{!opts->nocolor}; + using Color = MaybeAnsi::Color; + if (!opts->quiet) { + if (opts->lazycheck) + std::cout << "lazily "; - if (opts->lazycheck) - std::cout << "lazily "; + std::cout << "indexing maildir " << col.fg(Color::Green) + << store.metadata().root_maildir << col.reset() << " -> store " + << col.fg(Color::Green) << store.metadata().database_path << col.reset() + << std::endl; + } - std::cout << "indexing maildir " - << col.fg(Color::Green) << store.metadata().root_maildir - << col.reset() - << " -> store " - << col.fg(Color::Green) << store.metadata().database_path - << col.reset() - << std::endl; - } + Mu::Indexer::Config conf{}; + conf.cleanup = !opts->nocleanup; + conf.lazy_check = opts->lazycheck; - Mu::Indexer::Config conf{}; - conf.cleanup = !opts->nocleanup; - conf.lazy_check = opts->lazycheck; + install_sig_handler(); - install_sig_handler (); + auto& indexer{store.indexer()}; + indexer.start(conf); + while (!CaughtSignal && indexer.is_running()) { + if (!opts->quiet) + print_stats(indexer.progress(), !opts->nocolor); - auto& indexer{store.indexer()}; - indexer.start(conf); - while (!CaughtSignal && indexer.is_running()) { - if (!opts->quiet) - print_stats (indexer.progress(), !opts->nocolor); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); - std::this_thread::sleep_for(std::chrono::milliseconds(250)); + if (!opts->quiet) { + std::cout << "\r"; + std::cout.flush(); + } + } - if (!opts->quiet) { - std::cout << "\r"; - std::cout.flush(); - } - } + store.indexer().stop(); - store.indexer().stop(); + if (!opts->quiet) { + print_stats(store.indexer().progress(), !opts->nocolor); + std::cout << std::endl; + } - if (!opts->quiet) { - print_stats (store.indexer().progress(), !opts->nocolor); - std::cout << std::endl; - } - - return MU_OK; + return MU_OK; } diff --git a/mu/mu-cmd-script.cc b/mu/mu-cmd-script.cc index 48170ee7..3f119a3f 100644 --- a/mu/mu-cmd-script.cc +++ b/mu/mu-cmd-script.cc @@ -31,116 +31,126 @@ #include "mu-script.hh" #include "mu-runtime.hh" - #include "utils/mu-util.h" #include "utils/mu-str.h" - #define MU_GUILE_EXT ".scm" #define MU_GUILE_DESCR_PREFIX ";; INFO: " -#define COL(C) ((color)?C:"") +#define COL(C) ((color) ? C : "") using namespace Mu; static void -print_script (const char *name, const char *oneline, const char *descr, - gboolean color, gboolean verbose) +print_script(const char* name, + const char* oneline, + const char* descr, + gboolean color, + gboolean verbose) { - g_print ("%s%s%s%s%s%s%s%s", - verbose ? "\n" : " * ", - COL(MU_COLOR_GREEN),name,COL(MU_COLOR_DEFAULT), - oneline ? ": " : "", - COL(MU_COLOR_BLUE),oneline ? oneline :"",MU_COLOR_DEFAULT); + g_print("%s%s%s%s%s%s%s%s", + verbose ? "\n" : " * ", + COL(MU_COLOR_GREEN), + name, + COL(MU_COLOR_DEFAULT), + oneline ? ": " : "", + COL(MU_COLOR_BLUE), + oneline ? oneline : "", + MU_COLOR_DEFAULT); if (verbose && descr) - g_print ("%s%s%s", - COL(MU_COLOR_MAGENTA),descr,COL(MU_COLOR_DEFAULT)); + g_print("%s%s%s", COL(MU_COLOR_MAGENTA), descr, COL(MU_COLOR_DEFAULT)); } - static gboolean -print_scripts (GSList *scripts, gboolean color, - gboolean verbose, const char *rxstr, GError **err) +print_scripts(GSList* scripts, gboolean color, gboolean verbose, const char* rxstr, GError** err) { - GSList *cur; - const char *verb; + GSList* cur; + const char* verb; if (!scripts) { - g_print ("No scripts available\n"); + g_print("No scripts available\n"); return TRUE; /* not an error */ } verb = verbose ? "" : " (use --verbose for details)"; if (rxstr) - g_print ("Available scripts matching '%s'%s:\n", - rxstr, verb); + g_print("Available scripts matching '%s'%s:\n", rxstr, verb); else - g_print ("Available scripts%s:\n", verb); + g_print("Available scripts%s:\n", verb); - for (cur = scripts; cur; cur = g_slist_next (cur)) { - - MuScriptInfo *msi; - const char* descr, *oneline, *name; + for (cur = scripts; cur; cur = g_slist_next(cur)) { + MuScriptInfo* msi; + const char * descr, *oneline, *name; msi = (MuScriptInfo*)cur->data; - name = mu_script_info_name (msi); - oneline = mu_script_info_one_line (msi); - descr = mu_script_info_description (msi); + name = mu_script_info_name(msi); + oneline = mu_script_info_one_line(msi); + descr = mu_script_info_description(msi); /* if rxstr is provide, only consider matching scriptinfos */ - if (rxstr && !mu_script_info_matches_regex (msi, rxstr, err)) { + if (rxstr && !mu_script_info_matches_regex(msi, rxstr, err)) { if (err && *err) return FALSE; continue; } - print_script (name, oneline, descr, color, verbose); + print_script(name, oneline, descr, color, verbose); } return TRUE; } +static char* +get_userpath(const char* muhome) +{ + if (muhome) + return g_build_path(G_DIR_SEPARATOR_S, muhome, "scripts", NULL); + else + return g_build_path(G_DIR_SEPARATOR_S, + g_get_user_data_dir(), + "mu", + "scripts", + NULL); +} static GSList* -get_script_info_list (const char *muhome, GError **err) +get_script_info_list(const char* muhome, GError** err) { GSList *scripts, *userscripts, *last; - char *userpath; + char* userpath; - scripts = mu_script_get_script_info_list - (MU_SCRIPTS_DIR, MU_GUILE_EXT, - MU_GUILE_DESCR_PREFIX, - err); + scripts = mu_script_get_script_info_list(MU_SCRIPTS_DIR, + MU_GUILE_EXT, + MU_GUILE_DESCR_PREFIX, + err); if (err && *err) return NULL; - userpath = g_strdup_printf ("%s%c%s", - muhome, G_DIR_SEPARATOR, "scripts"); + userpath = get_userpath(muhome); /* is there are userdir for scripts? */ - if (!mu_util_check_dir (userpath, TRUE, FALSE)) { - g_free (userpath); + if (!mu_util_check_dir(userpath, TRUE, FALSE)) { + g_free(userpath); return scripts; } /* append it to the list we already have */ - userscripts = mu_script_get_script_info_list (userpath, MU_GUILE_EXT, - MU_GUILE_DESCR_PREFIX, - err); - g_free (userpath); + userscripts = + mu_script_get_script_info_list(userpath, MU_GUILE_EXT, MU_GUILE_DESCR_PREFIX, err); + g_free(userpath); /* some error, return nothing */ if (err && *err) { - mu_script_info_list_destroy (userscripts); - mu_script_info_list_destroy (scripts); + mu_script_info_list_destroy(userscripts); + mu_script_info_list_destroy(scripts); return NULL; } /* append the user scripts */ - last = g_slist_last (scripts); + last = g_slist_last(scripts); if (last) { last->next = userscripts; return scripts; @@ -148,57 +158,51 @@ get_script_info_list (const char *muhome, GError **err) return userscripts; /* apparently, scripts was NULL */ } - - static gboolean -check_params (const MuConfig *opts, GError **err) +check_params(const MuConfig* opts, GError** err) { - if (!mu_util_supports (MU_FEATURE_GUILE)) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "the 'script' command is not available " - "in this version of mu"); + if (!mu_util_supports(MU_FEATURE_GUILE)) { + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "the 'script' command is not available " + "in this version of mu"); return FALSE; } return TRUE; } - MuError -Mu::mu_cmd_script (const MuConfig *opts, GError **err) +Mu::mu_cmd_script(const MuConfig* opts, GError** err) { - MuScriptInfo *msi; - GSList *scripts; + MuScriptInfo* msi; + GSList* scripts; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_SCRIPT, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_SCRIPT, MU_ERROR_INTERNAL); - if (!check_params (opts, err)) + if (!check_params(opts, err)) return MU_ERROR; - scripts = get_script_info_list (opts->muhome, err); + scripts = get_script_info_list(opts->muhome, err); if (err && *err) goto leave; - if (g_strcmp0 (opts->cmdstr, "script") == 0) { - print_scripts (scripts, !opts->nocolor, opts->verbose, - opts->script_params[0], err); + if (g_strcmp0(opts->cmdstr, "script") == 0) { + print_scripts(scripts, !opts->nocolor, opts->verbose, opts->script_params[0], err); goto leave; } - msi = mu_script_find_script_with_name (scripts, opts->script); + msi = mu_script_find_script_with_name(scripts, opts->script); if (!msi) { - mu_util_g_set_error (err, MU_ERROR_SCRIPT_NOT_FOUND, - "command or script not found"); + mu_util_g_set_error(err, MU_ERROR_SCRIPT_NOT_FOUND, "command or script not found"); goto leave; } /* do it! */ - mu_script_guile_run (msi, mu_runtime_path(MU_RUNTIME_PATH_CACHE), - opts->script_params, err); + mu_script_guile_run(msi, mu_runtime_path(MU_RUNTIME_PATH_CACHE), opts->script_params, err); leave: /* this won't be reached, unless there is some error */ - mu_script_info_list_destroy (scripts); + mu_script_info_list_destroy(scripts); return (err && *err) ? MU_ERROR : MU_OK; } diff --git a/mu/mu-cmd-server.cc b/mu/mu-cmd-server.cc index 61857318..93a05fab 100644 --- a/mu/mu-cmd-server.cc +++ b/mu/mu-cmd-server.cc @@ -30,31 +30,30 @@ #include "mu-cmd.hh" #include "mu-server.hh" - #include "utils/mu-utils.hh" #include "utils/mu-command-parser.hh" #include "utils/mu-readline.hh" using namespace Mu; static std::atomic MuTerminate{false}; -static bool tty; +static bool tty; static void -install_sig_handler (void) +install_sig_handler(void) { - struct sigaction action; - int i, sigs[] = { SIGINT, SIGHUP, SIGTERM, SIGPIPE }; + struct sigaction action; + int i, sigs[] = {SIGINT, SIGHUP, SIGTERM, SIGPIPE}; - MuTerminate = false; + MuTerminate = false; - action.sa_handler = [](int sig){ MuTerminate = true; }; - sigemptyset(&action.sa_mask); - action.sa_flags = SA_RESETHAND; + action.sa_handler = [](int sig) { MuTerminate = true; }; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_RESETHAND; - for (i = 0; i != G_N_ELEMENTS(sigs); ++i) - if (sigaction (sigs[i], &action, NULL) != 0) - g_critical ("set sigaction for %d failed: %s", - sigs[i], g_strerror (errno));; + for (i = 0; i != G_N_ELEMENTS(sigs); ++i) + if (sigaction(sigs[i], &action, NULL) != 0) + g_critical("set sigaction for %d failed: %s", sigs[i], g_strerror(errno)); + ; } /* @@ -68,85 +67,86 @@ install_sig_handler (void) static void cookie(size_t n) { - const auto num{static_cast(n)}; + const auto num{static_cast(n)}; - if (tty) // for testing. - ::printf ("[%x]", num); - else - ::printf (COOKIE_PRE "%x" COOKIE_POST, num); + if (tty) // for testing. + ::printf("[%x]", num); + else + ::printf(COOKIE_PRE "%x" COOKIE_POST, num); } static void -output_sexp_stdout (Sexp&& sexp) +output_sexp_stdout(Sexp&& sexp) { - const auto str{sexp.to_sexp_string()}; - cookie(str.size() + 1); - if (G_UNLIKELY(::puts(str.c_str()) < 0)) { - g_critical ("failed to write output '%s'", str.c_str()); - ::raise (SIGTERM); /* terminate ourselves */ - } + const auto str{sexp.to_sexp_string()}; + cookie(str.size() + 1); + if (G_UNLIKELY(::puts(str.c_str()) < 0)) { + g_critical("failed to write output '%s'", str.c_str()); + ::raise(SIGTERM); /* terminate ourselves */ + } } static void report_error(const Mu::Error& err) noexcept { - Sexp::List e; + Sexp::List e; - e.add_prop(":error", Sexp::make_number(static_cast(err.code()))); - e.add_prop(":message", Sexp::make_string(err.what())); + e.add_prop(":error", Sexp::make_number(static_cast(err.code()))); + e.add_prop(":message", Sexp::make_string(err.what())); - output_sexp_stdout(Sexp::make_list(std::move(e))); + output_sexp_stdout(Sexp::make_list(std::move(e))); } MuError -Mu::mu_cmd_server (const MuConfig *opts, GError **err) try { +Mu::mu_cmd_server(const MuConfig* opts, GError** err) +try { + Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false /*writable*/}; + Server server{store, output_sexp_stdout}; - Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false/*writable*/}; - Server server{store, output_sexp_stdout}; + g_message("created server with store @ %s; maildir @ %s; debug-mode %s", + store.metadata().database_path.c_str(), + store.metadata().root_maildir.c_str(), + opts->debug ? "yes" : "no"); - g_message ("created server with store @ %s; maildir @ %s; debug-mode %s", - store.metadata().database_path.c_str(), - store.metadata().root_maildir.c_str(), - opts->debug ? "yes" : "no"); + tty = ::isatty(::fileno(stdout)); - tty = ::isatty(::fileno(stdout)); + const auto eval = std::string{opts->commands ? "(help :full t)" + : opts->eval ? opts->eval + : ""}; + if (!eval.empty()) { + server.invoke(eval); + return MU_OK; + } - const auto eval = std::string { - opts->commands ? "(help :full t)" : opts->eval ? opts->eval : ""}; - if (!eval.empty()) { - server.invoke(eval); - return MU_OK; - } + // Note, the readline stuff is inactive unless on a tty. + const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"}; + setup_readline(histpath, 50); - // Note, the readline stuff is inactive unless on a tty. - const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"}; - setup_readline(histpath, 50); + install_sig_handler(); + std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n" + << ";; Use (help) to get a list of commands, (quit) to quit.\n"; - install_sig_handler(); - std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n" - << ";; Use (help) to get a list of commands, (quit) to quit.\n"; + bool do_quit{}; + while (!MuTerminate && !do_quit) { + std::fflush(stdout); // Needed for Windows, see issue #1827. + const auto line{read_line(do_quit)}; + if (line.find_first_not_of(" \t") == std::string::npos) + continue; // skip whitespace-only lines - bool do_quit{}; - while (!MuTerminate && !do_quit) { - std::fflush(stdout); // Needed for Windows, see issue #1827. - const auto line{read_line(do_quit)}; - if (line.find_first_not_of(" \t") == std::string::npos) - continue; // skip whitespace-only lines + do_quit = server.invoke(line) ? false : true; + save_line(line); + } + shutdown_readline(); - do_quit = server.invoke(line) ? false : true; - save_line(line); - } - shutdown_readline(); - - return MU_OK; + return MU_OK; } catch (const Error& er) { - /* note: user-level error, "OK" for mu */ - report_error(er); - g_warning ("server caught exception: %s", er.what()); - return MU_OK; + /* note: user-level error, "OK" for mu */ + report_error(er); + g_warning("server caught exception: %s", er.what()); + return MU_OK; } catch (...) { - g_critical ("server caught exception"); - g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception"); - return MU_ERROR; + g_critical("server caught exception"); + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception"); + return MU_ERROR; } diff --git a/mu/mu-cmd.cc b/mu/mu-cmd.cc index 49891bb2..878185f3 100644 --- a/mu/mu-cmd.cc +++ b/mu/mu-cmd.cc @@ -28,7 +28,6 @@ #include #include - #include "mu-msg.hh" #include "mu-msg-part.hh" #include "mu-cmd.hh" @@ -48,223 +47,205 @@ using namespace Mu; static gboolean -view_msg_sexp (MuMsg *msg, const MuConfig *opts) +view_msg_sexp(MuMsg* msg, const MuConfig* opts) { - ::fputs(msg_to_sexp(msg,0, mu_config_get_msg_options(opts)) - .to_sexp_string(). c_str(), stdout); + ::fputs(msg_to_sexp(msg, 0, mu_config_get_msg_options(opts)).to_sexp_string().c_str(), + stdout); return TRUE; } - static void -each_part (MuMsg *msg, MuMsgPart *part, gchar **attach) +each_part(MuMsg* msg, MuMsgPart* part, gchar** attach) { char *fname, *tmp; - if (!mu_msg_part_maybe_attachment (part)) + if (!mu_msg_part_maybe_attachment(part)) return; - fname = mu_msg_part_get_filename (part, FALSE); + fname = mu_msg_part_get_filename(part, FALSE); if (!fname) return; - tmp = *attach; - *attach = g_strdup_printf ("%s%s'%s'", - *attach ? *attach : "", - *attach ? ", " : "", - fname); - g_free (tmp); + tmp = *attach; + *attach = g_strdup_printf("%s%s'%s'", *attach ? *attach : "", *attach ? ", " : "", fname); + g_free(tmp); } /* return comma-sep'd list of attachments */ -static gchar * -get_attach_str (MuMsg *msg, const MuConfig *opts) +static gchar* +get_attach_str(MuMsg* msg, const MuConfig* opts) { - gchar *attach; + gchar* attach; - const auto msgopts = (MuMsgOptions) - (mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD); + const auto msgopts = + (MuMsgOptions)(mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD); attach = NULL; - mu_msg_part_foreach (msg, msgopts, - (MuMsgPartForeachFunc)each_part, &attach); + mu_msg_part_foreach(msg, msgopts, (MuMsgPartForeachFunc)each_part, &attach); return attach; } -#define color_maybe(C) do { if(color) fputs ((C),stdout);} while(0) +#define color_maybe(C) \ + do { \ + if (color) \ + fputs((C), stdout); \ + } while (0) static void -print_field (const char* field, const char *val, gboolean color) +print_field(const char* field, const char* val, gboolean color) { if (!val) return; - color_maybe (MU_COLOR_MAGENTA); - mu_util_fputs_encoded (field, stdout); - color_maybe (MU_COLOR_DEFAULT); - fputs (": ", stdout); + color_maybe(MU_COLOR_MAGENTA); + mu_util_fputs_encoded(field, stdout); + color_maybe(MU_COLOR_DEFAULT); + fputs(": ", stdout); if (val) { - color_maybe (MU_COLOR_GREEN); - mu_util_fputs_encoded (val, stdout); + color_maybe(MU_COLOR_GREEN); + mu_util_fputs_encoded(val, stdout); } - color_maybe (MU_COLOR_DEFAULT); - fputs ("\n", stdout); + color_maybe(MU_COLOR_DEFAULT); + fputs("\n", stdout); } - /* a summary_len of 0 mean 'don't show summary, show body */ static void -body_or_summary (MuMsg *msg, const MuConfig *opts) +body_or_summary(MuMsg* msg, const MuConfig* opts) { - const char *body; + const char* body; gboolean color; - int my_opts = mu_config_get_msg_options(opts) | - MU_MSG_OPTION_CONSOLE_PASSWORD; + int my_opts = mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD; color = !opts->nocolor; - body = mu_msg_get_body_text (msg, (MuMsgOptions)my_opts); + body = mu_msg_get_body_text(msg, (MuMsgOptions)my_opts); if (!body) { - if (mu_msg_get_flags (msg) & MU_FLAG_ENCRYPTED) { - color_maybe (MU_COLOR_CYAN); - g_print ("[No body found; " - "message has encrypted parts]\n"); + if (mu_msg_get_flags(msg) & MU_FLAG_ENCRYPTED) { + color_maybe(MU_COLOR_CYAN); + g_print("[No body found; " + "message has encrypted parts]\n"); } else { - color_maybe (MU_COLOR_MAGENTA); - g_print ("[No body found]\n"); + color_maybe(MU_COLOR_MAGENTA); + g_print("[No body found]\n"); } - color_maybe (MU_COLOR_DEFAULT); + color_maybe(MU_COLOR_DEFAULT); return; } if (opts->summary_len != 0) { - gchar *summ; - summ = mu_str_summarize (body, opts->summary_len); - print_field ("Summary", summ, color); - g_free (summ); + gchar* summ; + summ = mu_str_summarize(body, opts->summary_len); + print_field("Summary", summ, color); + g_free(summ); } else { - mu_util_print_encoded ("%s", body); - if (!g_str_has_suffix (body, "\n")) - g_print ("\n"); + mu_util_print_encoded("%s", body); + if (!g_str_has_suffix(body, "\n")) + g_print("\n"); } } - /* we ignore fields for now */ /* summary_len == 0 means "no summary */ static gboolean -view_msg_plain (MuMsg *msg, const MuConfig *opts) +view_msg_plain(MuMsg* msg, const MuConfig* opts) { - gchar *attachs; - time_t date; - const GSList *lst; - gboolean color; + gchar* attachs; + time_t date; + const GSList* lst; + gboolean color; color = !opts->nocolor; - print_field ("From", mu_msg_get_from (msg), color); - print_field ("To", mu_msg_get_to (msg), color); - print_field ("Cc", mu_msg_get_cc (msg), color); - print_field ("Bcc", mu_msg_get_bcc (msg), color); - print_field ("Subject", mu_msg_get_subject (msg), color); + print_field("From", mu_msg_get_from(msg), color); + print_field("To", mu_msg_get_to(msg), color); + print_field("Cc", mu_msg_get_cc(msg), color); + print_field("Bcc", mu_msg_get_bcc(msg), color); + print_field("Subject", mu_msg_get_subject(msg), color); - if ((date = mu_msg_get_date (msg))) - print_field ("Date", mu_date_str_s ("%c", date), - color); + if ((date = mu_msg_get_date(msg))) + print_field("Date", mu_date_str_s("%c", date), color); - if ((lst = mu_msg_get_tags (msg))) { - gchar *tags; - tags = mu_str_from_list (lst,','); - print_field ("Tags", tags, color); - g_free (tags); + if ((lst = mu_msg_get_tags(msg))) { + gchar* tags; + tags = mu_str_from_list(lst, ','); + print_field("Tags", tags, color); + g_free(tags); } - if ((attachs = get_attach_str (msg, opts))) { - print_field ("Attachments", attachs, color); - g_free (attachs); + if ((attachs = get_attach_str(msg, opts))) { + print_field("Attachments", attachs, color); + g_free(attachs); } - body_or_summary (msg, opts); + body_or_summary(msg, opts); return TRUE; } - static gboolean -handle_msg (const char *fname, const MuConfig *opts, GError **err) +handle_msg(const char* fname, const MuConfig* opts, GError** err) { - MuMsg *msg; + MuMsg* msg; gboolean rv; - msg = mu_msg_new_from_file (fname, NULL, err); + msg = mu_msg_new_from_file(fname, NULL, err); if (!msg) return FALSE; switch (opts->format) { - case MU_CONFIG_FORMAT_PLAIN: - rv = view_msg_plain (msg, opts); - break; - case MU_CONFIG_FORMAT_SEXP: - rv = view_msg_sexp (msg, opts); - break; - default: - g_critical ("bug: should not be reached"); - rv = FALSE; + case MU_CONFIG_FORMAT_PLAIN: rv = view_msg_plain(msg, opts); break; + case MU_CONFIG_FORMAT_SEXP: rv = view_msg_sexp(msg, opts); break; + default: g_critical("bug: should not be reached"); rv = FALSE; } - mu_msg_unref (msg); + mu_msg_unref(msg); return rv; } static gboolean -view_params_valid (const MuConfig *opts, GError **err) +view_params_valid(const MuConfig* opts, GError** err) { /* note: params[0] will be 'view' */ if (!opts->params[0] || !opts->params[1]) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "error in parameters"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "error in parameters"); return FALSE; } switch (opts->format) { case MU_CONFIG_FORMAT_PLAIN: - case MU_CONFIG_FORMAT_SEXP: - break; + case MU_CONFIG_FORMAT_SEXP: break; default: - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "invalid output format"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "invalid output format"); return FALSE; } return TRUE; } - static MuError -cmd_view (const MuConfig *opts, GError **err) +cmd_view(const MuConfig* opts, GError** err) { - int i; + int i; gboolean rv; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VIEW, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_VIEW, MU_ERROR_INTERNAL); - rv = view_params_valid (opts, err); + rv = view_params_valid(opts, err); if (!rv) goto leave; for (i = 1; opts->params[i]; ++i) { - - rv = handle_msg (opts->params[i], opts, err); + rv = handle_msg(opts->params[i], opts, err); if (!rv) break; /* add a separator between two messages? */ if (opts->terminator) - g_print ("%c", VIEW_TERMINATOR); + g_print("%c", VIEW_TERMINATOR); } leave: @@ -275,189 +256,173 @@ leave: } static MuError -cmd_mkdir (const MuConfig *opts, GError **err) +cmd_mkdir(const MuConfig* opts, GError** err) { int i; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_MKDIR, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_MKDIR, MU_ERROR_INTERNAL); if (!opts->params[1]) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing directory parameter"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing directory parameter"); return MU_ERROR_IN_PARAMETERS; } for (i = 1; opts->params[i]; ++i) - if (!mu_maildir_mkdir (opts->params[i], opts->dirmode, - FALSE, err)) - return err && *err ? (MuError)(*err)->code : - MU_ERROR_FILE_CANNOT_MKDIR; + if (!mu_maildir_mkdir(opts->params[i], opts->dirmode, FALSE, err)) + return err && *err ? (MuError)(*err)->code : MU_ERROR_FILE_CANNOT_MKDIR; return MU_OK; } - static gboolean -check_file_okay (const char *path, gboolean cmd_add) +check_file_okay(const char* path, gboolean cmd_add) { - if (!g_path_is_absolute (path)) { - g_printerr ("path is not absolute: %s\n", path); + if (!g_path_is_absolute(path)) { + g_printerr("path is not absolute: %s\n", path); return FALSE; } if (cmd_add && access(path, R_OK) != 0) { - g_printerr ("path is not readable: %s: %s\n", - path, g_strerror (errno)); + g_printerr("path is not readable: %s: %s\n", path, g_strerror(errno)); return FALSE; } return TRUE; } -typedef bool (*ForeachMsgFunc) (Mu::Store& store, const char *path, GError **err); +typedef bool (*ForeachMsgFunc)(Mu::Store& store, const char* path, GError** err); static MuError -foreach_msg_file (Mu::Store& store, const MuConfig *opts, - ForeachMsgFunc foreach_func, GError **err) +foreach_msg_file(Mu::Store& store, const MuConfig* opts, ForeachMsgFunc foreach_func, GError** err) { - unsigned u; - gboolean all_ok; + unsigned u; + gboolean all_ok; /* note: params[0] will be 'add' */ if (!opts->params[0] || !opts->params[1]) { - g_print ("usage: mu %s []\n", - opts->params[0] ? opts->params[0] : ""); - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing parameters"); + g_print("usage: mu %s []\n", + opts->params[0] ? opts->params[0] : ""); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing parameters"); return MU_ERROR_IN_PARAMETERS; } for (u = 1, all_ok = TRUE; opts->params[u]; ++u) { - const char* path; path = opts->params[u]; - if (!check_file_okay (path, TRUE)) { + if (!check_file_okay(path, TRUE)) { all_ok = FALSE; - g_printerr ("not a valid message file: %s\n", path); + g_printerr("not a valid message file: %s\n", path); continue; } - if (!foreach_func (store, path, err)) { + if (!foreach_func(store, path, err)) { all_ok = FALSE; - g_printerr ("error with %s: %s\n", path, - (err&&*err) ? (*err)->message : - "something went wrong"); - g_clear_error (err); + g_printerr("error with %s: %s\n", + path, + (err && *err) ? (*err)->message : "something went wrong"); + g_clear_error(err); continue; } } if (!all_ok) { - mu_util_g_set_error (err, MU_ERROR_XAPIAN_STORE_FAILED, - "%s failed for some message(s)", - opts->params[0]); + mu_util_g_set_error(err, + MU_ERROR_XAPIAN_STORE_FAILED, + "%s failed for some message(s)", + opts->params[0]); return MU_ERROR_XAPIAN_STORE_FAILED; } return MU_OK; } - static bool -add_path_func (Mu::Store& store, const char *path, GError **err) +add_path_func(Mu::Store& store, const char* path, GError** err) { - const auto docid = store.add_message (path); - g_debug ("added message @ %s, docid=%u", path, docid); + const auto docid = store.add_message(path); + g_debug("added message @ %s, docid=%u", path, docid); - return true; -} - - -static MuError -cmd_add (Mu::Store& store, const MuConfig *opts, GError **err) -{ - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_ADD, - MU_ERROR_INTERNAL); - - return foreach_msg_file (store, opts, add_path_func, err); -} - -static bool -remove_path_func (Mu::Store& store, const char *path, GError **err) -{ - const auto res = store.remove_message (path); - g_debug ("removed %s (%s)", path, res ? "yes" : "no"); - - return true; + return true; } static MuError -cmd_remove (Mu::Store& store, const MuConfig *opts, GError **err) +cmd_add(Mu::Store& store, const MuConfig* opts, GError** err) { - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_ADD, MU_ERROR_INTERNAL); - return foreach_msg_file (store, opts, remove_path_func, err); + return foreach_msg_file(store, opts, add_path_func, err); } static bool -tickle_func (Mu::Store& store, const char *path, GError **err) +remove_path_func(Mu::Store& store, const char* path, GError** err) { - MuMsg *msg{mu_msg_new_from_file (path, NULL, err)}; + const auto res = store.remove_message(path); + g_debug("removed %s (%s)", path, res ? "yes" : "no"); + + return true; +} + +static MuError +cmd_remove(Mu::Store& store, const MuConfig* opts, GError** err) +{ + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_REMOVE, MU_ERROR_INTERNAL); + + return foreach_msg_file(store, opts, remove_path_func, err); +} + +static bool +tickle_func(Mu::Store& store, const char* path, GError** err) +{ + MuMsg* msg{mu_msg_new_from_file(path, NULL, err)}; if (!msg) return false; - const auto res = mu_msg_tickle (msg, err); - g_debug ("tickled %s (%s)", path, res ? "ok" : "failed"); - mu_msg_unref (msg); + const auto res = mu_msg_tickle(msg, err); + g_debug("tickled %s (%s)", path, res ? "ok" : "failed"); + mu_msg_unref(msg); return res == TRUE; } - static MuError -cmd_tickle (Mu::Store& store, const MuConfig *opts, GError **err) +cmd_tickle(Mu::Store& store, const MuConfig* opts, GError** err) { - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_TICKLE, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_TICKLE, MU_ERROR_INTERNAL); - return foreach_msg_file (store, opts, tickle_func, err); + return foreach_msg_file(store, opts, tickle_func, err); } struct _VData { MuMsgPartSigStatus combined_status; - char *report; - gboolean oneline; + char* report; + gboolean oneline; }; typedef struct _VData VData; static void -each_sig (MuMsg *msg, MuMsgPart *part, VData *vdata) +each_sig(MuMsg* msg, MuMsgPart* part, VData* vdata) { - MuMsgPartSigStatusReport *report; + MuMsgPartSigStatusReport* report; report = part->sig_status_report; if (!report) return; if (vdata->oneline) - vdata->report = g_strdup_printf - ("%s%s%s", - vdata->report ? vdata->report : "", - vdata->report ? "; " : "", - report->report); + vdata->report = g_strdup_printf("%s%s%s", + vdata->report ? vdata->report : "", + vdata->report ? "; " : "", + report->report); else - vdata->report = g_strdup_printf - ("%s%s\t%s", - vdata->report ? vdata->report : "", - vdata->report ? "\n" : "", - report->report); + vdata->report = g_strdup_printf("%s%s\t%s", + vdata->report ? vdata->report : "", + vdata->report ? "\n" : "", + report->report); if (vdata->combined_status == MU_MSG_PART_SIG_STATUS_BAD || vdata->combined_status == MU_MSG_PART_SIG_STATUS_ERROR) @@ -466,170 +431,157 @@ each_sig (MuMsg *msg, MuMsgPart *part, VData *vdata) vdata->combined_status = report->verdict; } - static void -print_verdict (VData *vdata, gboolean color, gboolean verbose) +print_verdict(VData* vdata, gboolean color, gboolean verbose) { - g_print ("verdict: "); + g_print("verdict: "); switch (vdata->combined_status) { - case MU_MSG_PART_SIG_STATUS_UNSIGNED: - g_print ("no signature found"); - break; + case MU_MSG_PART_SIG_STATUS_UNSIGNED: g_print("no signature found"); break; case MU_MSG_PART_SIG_STATUS_GOOD: - color_maybe (MU_COLOR_GREEN); - g_print ("signature(s) verified"); + color_maybe(MU_COLOR_GREEN); + g_print("signature(s) verified"); break; case MU_MSG_PART_SIG_STATUS_BAD: - color_maybe (MU_COLOR_RED); - g_print ("bad signature"); + color_maybe(MU_COLOR_RED); + g_print("bad signature"); break; case MU_MSG_PART_SIG_STATUS_ERROR: - color_maybe (MU_COLOR_RED); - g_print ("verification failed"); + color_maybe(MU_COLOR_RED); + g_print("verification failed"); break; case MU_MSG_PART_SIG_STATUS_FAIL: color_maybe(MU_COLOR_RED); - g_print ("error in verification process"); + g_print("error in verification process"); break; - default: g_return_if_reached (); + default: g_return_if_reached(); } - color_maybe (MU_COLOR_DEFAULT); + color_maybe(MU_COLOR_DEFAULT); if (vdata->report && verbose) - g_print ("%s%s\n", - (vdata->oneline) ? ";" : "\n", - vdata->report); + g_print("%s%s\n", (vdata->oneline) ? ";" : "\n", vdata->report); else - g_print ("\n"); + g_print("\n"); } - static MuError -cmd_verify (const MuConfig *opts, GError **err) +cmd_verify(const MuConfig* opts, GError** err) { - MuMsg *msg; + MuMsg* msg; int msgopts; VData vdata; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); - g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY, - MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_VERIFY, MU_ERROR_INTERNAL); if (!opts->params[1]) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing message-file parameter"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing message-file parameter"); return MU_ERROR_IN_PARAMETERS; } - msg = mu_msg_new_from_file (opts->params[1], NULL, err); + msg = mu_msg_new_from_file(opts->params[1], NULL, err); if (!msg) return MU_ERROR; - msgopts = mu_config_get_msg_options (opts) - | MU_MSG_OPTION_VERIFY - | MU_MSG_OPTION_CONSOLE_PASSWORD; + msgopts = + mu_config_get_msg_options(opts) | MU_MSG_OPTION_VERIFY | MU_MSG_OPTION_CONSOLE_PASSWORD; - vdata.report = NULL; + vdata.report = NULL; vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED; - vdata.oneline = FALSE; + vdata.oneline = FALSE; - mu_msg_part_foreach (msg, (MuMsgOptions)msgopts, - (MuMsgPartForeachFunc)each_sig, &vdata); + mu_msg_part_foreach(msg, (MuMsgOptions)msgopts, (MuMsgPartForeachFunc)each_sig, &vdata); if (!opts->quiet) - print_verdict (&vdata, !opts->nocolor, opts->verbose); + print_verdict(&vdata, !opts->nocolor, opts->verbose); - mu_msg_unref (msg); - g_free (vdata.report); + mu_msg_unref(msg); + g_free(vdata.report); - return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ? - MU_OK : MU_ERROR; + return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ? MU_OK : MU_ERROR; } template -static void key_val(const Mu::MaybeAnsi& col, const std::string& key, T val) +static void +key_val(const Mu::MaybeAnsi& col, const std::string& key, T val) { - using Color = Mu::MaybeAnsi::Color; + using Color = Mu::MaybeAnsi::Color; - std::cout << col.fg(Color::BrightBlue) - << std::left << std::setw(18) << key - << col.reset() << ": "; + std::cout << col.fg(Color::BrightBlue) << std::left << std::setw(18) << key << col.reset() + << ": "; - std::cout << col.fg(Color::Green) - << val << col.reset() << "\n"; + std::cout << col.fg(Color::Green) << val << col.reset() << "\n"; } - static MuError -cmd_info (const Mu::Store& store, const MuConfig *opts, GError **err) +cmd_info(const Mu::Store& store, const MuConfig* opts, GError** err) { - Mu::MaybeAnsi col{!opts->nocolor}; + Mu::MaybeAnsi col{!opts->nocolor}; - key_val(col, "maildir", store.metadata().root_maildir); - key_val(col, "database-path", store.metadata().database_path); - key_val(col, "schema-version", store.metadata().schema_version); - key_val(col, "max-message-size", store.metadata().max_message_size); - key_val(col, "batch-size", store.metadata().batch_size); - key_val(col, "messages in store", store.size()); + key_val(col, "maildir", store.metadata().root_maildir); + key_val(col, "database-path", store.metadata().database_path); + key_val(col, "schema-version", store.metadata().schema_version); + key_val(col, "max-message-size", store.metadata().max_message_size); + key_val(col, "batch-size", store.metadata().batch_size); + key_val(col, "messages in store", store.size()); const auto created{store.metadata().created}; - const auto tstamp{::localtime (&created)}; + const auto tstamp{::localtime(&created)}; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-y2k" - char tbuf[64]; - strftime (tbuf, sizeof(tbuf), "%c", tstamp); + char tbuf[64]; + strftime(tbuf, sizeof(tbuf), "%c", tstamp); #pragma GCC diagnostic pop - key_val(col, "created", tbuf); + key_val(col, "created", tbuf); const auto addrs{store.metadata().personal_addresses}; - if (addrs.empty()) - key_val(col, "personal-address", ""); - else - for (auto&& c: addrs) - key_val(col, "personal-address", c); + if (addrs.empty()) + key_val(col, "personal-address", ""); + else + for (auto&& c : addrs) + key_val(col, "personal-address", c); - return MU_OK; + return MU_OK; } static MuError -cmd_init (const MuConfig *opts, GError **err) +cmd_init(const MuConfig* opts, GError** err) { - /* not provided, nor could we find a good default */ - if (!opts->maildir) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "missing --maildir parameter and could " - "not determine default"); + /* not provided, nor could we find a good default */ + if (!opts->maildir) { + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "missing --maildir parameter and could " + "not determine default"); return MU_ERROR_IN_PARAMETERS; - } + } - if (opts->max_msg_size < 0) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "invalid value for max-message-size"); + if (opts->max_msg_size < 0) { + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "invalid value for max-message-size"); return MU_ERROR_IN_PARAMETERS; - } else if (opts->batch_size < 0) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "invalid value for batch-size"); + } else if (opts->batch_size < 0) { + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "invalid value for batch-size"); return MU_ERROR_IN_PARAMETERS; - } + } - Mu::Store::Config conf{}; - conf.max_message_size = opts->max_msg_size; - conf.batch_size = opts->batch_size; + Mu::Store::Config conf{}; + conf.max_message_size = opts->max_msg_size; + conf.batch_size = opts->batch_size; - Mu::StringVec my_addrs; - auto addrs = opts->my_addresses; - while (addrs && *addrs) { - my_addrs.emplace_back (*addrs); - ++addrs; - } + Mu::StringVec my_addrs; + auto addrs = opts->my_addresses; + while (addrs && *addrs) { + my_addrs.emplace_back(*addrs); + ++addrs; + } - Mu::Store store(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), - opts->maildir, my_addrs, conf); + Mu::Store store(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), opts->maildir, my_addrs, conf); if (!opts->quiet) { - cmd_info (store, opts, NULL); + cmd_info(store, opts, NULL); std::cout << "\nstore created; use the 'index' command to fill/update it.\n"; } @@ -637,49 +589,46 @@ cmd_init (const MuConfig *opts, GError **err) } static MuError -cmd_find (const MuConfig *opts, GError **err) +cmd_find(const MuConfig* opts, GError** err) { - Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/}; + Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true /*readonly*/}; - return mu_cmd_find(store, opts, err); + return mu_cmd_find(store, opts, err); } static void -show_usage (void) +show_usage(void) { - g_print ("usage: mu command [options] [parameters]\n"); - g_print ("where command is one of index, find, cfind, view, mkdir, " - "extract, add, remove, script, verify or server\n"); - g_print ("see the mu, mu- or mu-easy manpages for " - "more information\n"); + g_print("usage: mu command [options] [parameters]\n"); + g_print("where command is one of index, find, cfind, view, mkdir, " + "extract, add, remove, script, verify or server\n"); + g_print("see the mu, mu- or mu-easy manpages for " + "more information\n"); } -typedef MuError (*readonly_store_func) (const Mu::Store&, const MuConfig *, GError **err); -typedef MuError (*writable_store_func) (Mu::Store&, const MuConfig *, GError **err); - +typedef MuError (*readonly_store_func)(const Mu::Store&, const MuConfig*, GError** err); +typedef MuError (*writable_store_func)(Mu::Store&, const MuConfig*, GError** err); static MuError -with_readonly_store (readonly_store_func func, const MuConfig *opts, GError **err) +with_readonly_store(readonly_store_func func, const MuConfig* opts, GError** err) { - const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/}; - return func (store, opts, err); + const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true /*readonly*/}; + return func(store, opts, err); } static MuError -with_writable_store (writable_store_func func, const MuConfig *opts, GError **err) +with_writable_store(writable_store_func func, const MuConfig* opts, GError** err) { - Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false/*!readonly*/}; - return func (store, opts, err); + Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false /*!readonly*/}; + return func(store, opts, err); } - static gboolean -check_params (const MuConfig *opts, GError **err) +check_params(const MuConfig* opts, GError** err) { - if (!opts->params||!opts->params[0]) {/* no command? */ - show_usage (); - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "error in parameters"); + if (!opts->params || !opts->params[0]) { /* no command? */ + show_usage(); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "error in parameters"); return FALSE; } @@ -687,64 +636,58 @@ check_params (const MuConfig *opts, GError **err) } MuError -Mu::mu_cmd_execute (const MuConfig *opts, GError **err) try -{ +Mu::mu_cmd_execute(const MuConfig* opts, GError** err) +try { MuError merr; - g_return_val_if_fail (opts, MU_ERROR_INTERNAL); + g_return_val_if_fail(opts, MU_ERROR_INTERNAL); if (!check_params(opts, err)) return MU_G_ERROR_CODE(err); switch (opts->cmd) { - /* already handled in mu-config.c */ - case MU_CONFIG_CMD_HELP: return MU_OK; + case MU_CONFIG_CMD_HELP: + return MU_OK; - /* no store needed */ + /* no store needed */ - case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break; - case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break; - case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break; - case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break; - case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break; + case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir(opts, err); break; + case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script(opts, err); break; + case MU_CONFIG_CMD_VIEW: merr = cmd_view(opts, err); break; + case MU_CONFIG_CMD_VERIFY: merr = cmd_verify(opts, err); break; + case MU_CONFIG_CMD_EXTRACT: + merr = mu_cmd_extract(opts, err); + break; - /* read-only store */ + /* read-only store */ - case MU_CONFIG_CMD_CFIND: - merr = with_readonly_store (mu_cmd_cfind, opts, err); break; - case MU_CONFIG_CMD_FIND: - merr = cmd_find(opts, err); break; + case MU_CONFIG_CMD_CFIND: merr = with_readonly_store(mu_cmd_cfind, opts, err); break; + case MU_CONFIG_CMD_FIND: merr = cmd_find(opts, err); break; case MU_CONFIG_CMD_INFO: - merr = with_readonly_store (cmd_info, opts, err); break; + merr = with_readonly_store(cmd_info, opts, err); + break; - /* writable store */ + /* writable store */ - case MU_CONFIG_CMD_ADD: - merr = with_writable_store (cmd_add, opts, err); break; - case MU_CONFIG_CMD_REMOVE: - merr = with_writable_store (cmd_remove, opts, err); break; - case MU_CONFIG_CMD_TICKLE: - merr = with_writable_store (cmd_tickle, opts, err); break; - case MU_CONFIG_CMD_INDEX: - merr = with_writable_store (mu_cmd_index, opts, err); break; + case MU_CONFIG_CMD_ADD: merr = with_writable_store(cmd_add, opts, err); break; + case MU_CONFIG_CMD_REMOVE: merr = with_writable_store(cmd_remove, opts, err); break; + case MU_CONFIG_CMD_TICKLE: merr = with_writable_store(cmd_tickle, opts, err); break; + case MU_CONFIG_CMD_INDEX: merr = with_writable_store(mu_cmd_index, opts, err); break; /* commands instantiate store themselves */ - case MU_CONFIG_CMD_INIT: - merr = cmd_init (opts,err); break; - case MU_CONFIG_CMD_SERVER: - merr = mu_cmd_server (opts, err); break; + case MU_CONFIG_CMD_INIT: merr = cmd_init(opts, err); break; + case MU_CONFIG_CMD_SERVER: merr = mu_cmd_server(opts, err); break; - default: - merr = MU_ERROR_IN_PARAMETERS; break; + default: merr = MU_ERROR_IN_PARAMETERS; break; } return merr; } catch (const Mu::Error& er) { - g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what()); - return MU_ERROR; + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what()); + return MU_ERROR; } catch (...) { - g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception"); - return MU_ERROR; + g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception"); + return MU_ERROR; } diff --git a/mu/mu-cmd.hh b/mu/mu-cmd.hh index 403af3e1..786fe195 100644 --- a/mu/mu-cmd.hh +++ b/mu/mu-cmd.hh @@ -36,8 +36,7 @@ namespace Mu { * >MU_OK (0) results, MU_EXITCODE_NO_MATCHES if the command * succeeds but there no matches, some error code for all other errors */ -MuError mu_cmd_find (const Mu::Store& store, const MuConfig *opts, - GError **err); +MuError mu_cmd_find(const Mu::Store& store, const MuConfig* opts, GError** err); /** * execute the 'extract' command @@ -48,8 +47,7 @@ MuError mu_cmd_find (const Mu::Store& store, const MuConfig *opts, * @return MU_OK (0) if the command succeeds, * some error code otherwise */ -MuError mu_cmd_extract (const MuConfig *opts, GError **err); - +MuError mu_cmd_extract(const MuConfig* opts, GError** err); /** * execute the 'script' command @@ -60,7 +58,7 @@ MuError mu_cmd_extract (const MuConfig *opts, GError **err); * @return MU_OK (0) if the command succeeds, * some error code otherwise */ -MuError mu_cmd_script (const MuConfig *opts, GError **err); +MuError mu_cmd_script(const MuConfig* opts, GError** err); /** * execute the cfind command @@ -72,8 +70,7 @@ MuError mu_cmd_script (const MuConfig *opts, GError **err); * @return MU_OK (0) if the command succeeds, * some error code otherwise */ -MuError mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts, - GError **err); +MuError mu_cmd_cfind(const Mu::Store& store, const MuConfig* opts, GError** err); /** * execute some mu command, based on 'opts' @@ -83,7 +80,7 @@ MuError mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts, * * @return MU_OK if all went wall, some error code otherwise */ -MuError mu_cmd_execute (const MuConfig *opts, GError **err); +MuError mu_cmd_execute(const MuConfig* opts, GError** err); /** * execute the 'index' command @@ -95,7 +92,7 @@ MuError mu_cmd_execute (const MuConfig *opts, GError **err); * @return MU_OK (0) if the command succeeded, * some error code otherwise */ -MuError mu_cmd_index (Mu::Store& store, const MuConfig *opt, GError **err); +MuError mu_cmd_index(Mu::Store& store, const MuConfig* opt, GError** err); /** * execute the server command @@ -104,8 +101,7 @@ MuError mu_cmd_index (Mu::Store& store, const MuConfig *opt, GError **err); * * @return MU_OK (0) if the command succeeds, some error code otherwise */ -MuError mu_cmd_server (const MuConfig *opts, GError **err); - +MuError mu_cmd_server(const MuConfig* opts, GError** err); } // namespace Mu diff --git a/mu/mu-config.cc b/mu/mu-config.cc index bfa3ecfc..41f48a55 100644 --- a/mu/mu-config.cc +++ b/mu/mu-config.cc @@ -20,7 +20,7 @@ #include "config.h" #include -#include /* memset */ +#include /* memset */ #include #include @@ -34,59 +34,55 @@ static MuConfig MU_CONFIG; #define color_maybe(C) (MU_CONFIG.nocolor ? "" : (C)) static MuConfigFormat -get_output_format (const char *formatstr) +get_output_format(const char* formatstr) { int i; struct { - const char* name; - MuConfigFormat format; - } formats [] = { - {"mutt-alias", MU_CONFIG_FORMAT_MUTT_ALIAS}, - {"mutt-ab", MU_CONFIG_FORMAT_MUTT_AB}, - {"wl", MU_CONFIG_FORMAT_WL}, - {"csv", MU_CONFIG_FORMAT_CSV}, - {"org-contact", MU_CONFIG_FORMAT_ORG_CONTACT}, - {"bbdb", MU_CONFIG_FORMAT_BBDB}, - {"links", MU_CONFIG_FORMAT_LINKS}, - {"plain", MU_CONFIG_FORMAT_PLAIN}, - {"sexp", MU_CONFIG_FORMAT_SEXP}, - {"json", MU_CONFIG_FORMAT_JSON}, - {"xml", MU_CONFIG_FORMAT_XML}, - {"xquery", MU_CONFIG_FORMAT_XQUERY}, - {"mquery", MU_CONFIG_FORMAT_MQUERY}, - {"debug", MU_CONFIG_FORMAT_DEBUG} - }; + const char* name; + MuConfigFormat format; + } formats[] = {{"mutt-alias", MU_CONFIG_FORMAT_MUTT_ALIAS}, + {"mutt-ab", MU_CONFIG_FORMAT_MUTT_AB}, + {"wl", MU_CONFIG_FORMAT_WL}, + {"csv", MU_CONFIG_FORMAT_CSV}, + {"org-contact", MU_CONFIG_FORMAT_ORG_CONTACT}, + {"bbdb", MU_CONFIG_FORMAT_BBDB}, + {"links", MU_CONFIG_FORMAT_LINKS}, + {"plain", MU_CONFIG_FORMAT_PLAIN}, + {"sexp", MU_CONFIG_FORMAT_SEXP}, + {"json", MU_CONFIG_FORMAT_JSON}, + {"xml", MU_CONFIG_FORMAT_XML}, + {"xquery", MU_CONFIG_FORMAT_XQUERY}, + {"mquery", MU_CONFIG_FORMAT_MQUERY}, + {"debug", MU_CONFIG_FORMAT_DEBUG}}; for (i = 0; i != G_N_ELEMENTS(formats); i++) - if (strcmp (formats[i].name, formatstr) == 0) + if (strcmp(formats[i].name, formatstr) == 0) return formats[i].format; return MU_CONFIG_FORMAT_UNKNOWN; } - -#define expand_dir(D) \ - if ((D)) { \ - char *exp; \ - exp = mu_util_dir_expand((D)); \ - if (exp) { \ - g_free((D)); \ - (D) = exp; \ - } \ +#define expand_dir(D) \ + if ((D)) { \ + char* exp; \ + exp = mu_util_dir_expand((D)); \ + if (exp) { \ + g_free((D)); \ + (D) = exp; \ + } \ } - static void -set_group_mu_defaults () +set_group_mu_defaults() { /* If muhome is not set, we use the XDG Base Directory Specification * locations. */ if (MU_CONFIG.muhome) - expand_dir(MU_CONFIG.muhome); + expand_dir(MU_CONFIG.muhome); /* check for the MU_NOCOLOR or NO_COLOR env vars; but in any case don't * use colors unless we're writing to a tty */ - if (g_getenv (MU_NOCOLOR) != NULL || g_getenv ("NO_COLOR") != NULL) + if (g_getenv(MU_NOCOLOR) != NULL || g_getenv("NO_COLOR") != NULL) MU_CONFIG.nocolor = TRUE; if (!isatty(fileno(stdout)) || !isatty(fileno(stderr))) @@ -94,29 +90,67 @@ set_group_mu_defaults () } static GOptionGroup* -config_options_group_mu () +config_options_group_mu() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"debug", 'd', 0, G_OPTION_ARG_NONE, &MU_CONFIG.debug, - "print debug output to standard error (false)", NULL}, - {"quiet", 'q', 0, G_OPTION_ARG_NONE, &MU_CONFIG.quiet, - "don't give any progress information (false)", NULL}, - {"version", 'V', 0, G_OPTION_ARG_NONE, &MU_CONFIG.version, - "display version and copyright information (false)", NULL}, - {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.muhome, - "specify an alternative mu directory", ""}, - {"log-stderr", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.log_stderr, - "log to standard error (false)", NULL}, - {"nocolor", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocolor, - "don't use ANSI-colors in output (false)", NULL}, - {"verbose", 'v', 0, G_OPTION_ARG_NONE, &MU_CONFIG.verbose, - "verbose output (false)", NULL}, + GOptionGroup* og; + GOptionEntry entries[] = {{"debug", + 'd', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.debug, + "print debug output to standard error (false)", + NULL}, + {"quiet", + 'q', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.quiet, + "don't give any progress information (false)", + NULL}, + {"version", + 'V', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.version, + "display version and copyright information (false)", + NULL}, + {"muhome", + 0, + 0, + G_OPTION_ARG_FILENAME, + &MU_CONFIG.muhome, + "specify an alternative mu directory", + ""}, + {"log-stderr", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.log_stderr, + "log to standard error (false)", + NULL}, + {"nocolor", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.nocolor, + "don't use ANSI-colors in output (false)", + NULL}, + {"verbose", + 'v', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.verbose, + "verbose output (false)", + NULL}, - {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, - &MU_CONFIG.params, "parameters", NULL}, - {NULL, 0, 0, (GOptionArg)0, NULL, NULL, NULL} - }; + {G_OPTION_REMAINING, + 0, + 0, + G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.params, + "parameters", + NULL}, + {NULL, 0, 0, (GOptionArg)0, NULL, NULL, NULL}}; og = g_option_group_new("mu", "general mu options", "", NULL, NULL); g_option_group_add_entries(og, entries); @@ -125,218 +159,323 @@ config_options_group_mu () } static void -set_group_init_defaults () +set_group_init_defaults() { if (!MU_CONFIG.maildir) MU_CONFIG.maildir = mu_util_guess_maildir(); - expand_dir (MU_CONFIG.maildir); + expand_dir(MU_CONFIG.maildir); } static GOptionGroup* -config_options_group_init () +config_options_group_init() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.maildir, - "top of the maildir", ""}, - {"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY, - &MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times", - "
"}, - {"max-message-size", 0, 0, G_OPTION_ARG_INT, - &MU_CONFIG.max_msg_size, "Maximum allowed size for messages", - ""}, - {"batch-size", 0, 0, G_OPTION_ARG_INT, - &MU_CONFIG.batch_size, - "Number of changes in a database transaction batch", - ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"maildir", + 'm', + 0, + G_OPTION_ARG_FILENAME, + &MU_CONFIG.maildir, + "top of the maildir", + ""}, + {"my-address", + 0, + 0, + G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.my_addresses, + "my e-mail address; can be used multiple times", + "
"}, + {"max-message-size", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.max_msg_size, + "Maximum allowed size for messages", + ""}, + {"batch-size", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.batch_size, + "Number of changes in a database transaction batch", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("init", "Options for the 'init' command", - "", NULL, NULL); + og = g_option_group_new("init", "Options for the 'init' command", "", NULL, NULL); g_option_group_add_entries(og, entries); return og; } static gboolean -index_post_parse_func (GOptionContext *context, GOptionGroup *group, - gpointer data, GError **error) +index_post_parse_func(GOptionContext* context, GOptionGroup* group, gpointer data, GError** error) { - if (!MU_CONFIG.maildir && !MU_CONFIG.my_addresses) - return TRUE; + if (!MU_CONFIG.maildir && !MU_CONFIG.my_addresses) + return TRUE; - g_printerr ("%sNOTE%s: as of mu 1.3.8, 'mu index' no longer uses the\n" - "--maildir/-m or --my-address options.\n\n", - color_maybe(MU_COLOR_RED), color_maybe(MU_COLOR_DEFAULT)); - g_printerr ("Instead, these options should be passed to 'mu init'.\n"); - g_printerr ("See the mu-init(1) or the mu4e reference manual,\n'Initializing the message store' for details.\n\n"); + g_printerr("%sNOTE%s: as of mu 1.3.8, 'mu index' no longer uses the\n" + "--maildir/-m or --my-address options.\n\n", + color_maybe(MU_COLOR_RED), + color_maybe(MU_COLOR_DEFAULT)); + g_printerr("Instead, these options should be passed to 'mu init'.\n"); + g_printerr("See the mu-init(1) or the mu4e reference manual,\n'Initializing the message " + "store' for details.\n\n"); - return TRUE; + return TRUE; } - static GOptionGroup* -config_options_group_index () +config_options_group_index() { - GOptionGroup *og; - GOptionEntry entries[] = { - /* only here so we can tell users they are deprecated */ - {"maildir", 'm', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, - &MU_CONFIG.maildir, "top of the maildir", ""}, - {"my-address", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, - &MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times", - "
"}, + GOptionGroup* og; + GOptionEntry entries[] = {/* only here so we can tell users they are deprecated */ + {"maildir", + 'm', + G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_FILENAME, + &MU_CONFIG.maildir, + "top of the maildir", + ""}, + {"my-address", + 0, + G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.my_addresses, + "my e-mail address; can be used multiple times", + "
"}, - {"lazy-check", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.lazycheck, - "only check dir-timestamps (false)", NULL}, - {"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup, - "don't clean up the database after indexing (false)", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + {"lazy-check", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.lazycheck, + "only check dir-timestamps (false)", + NULL}, + {"nocleanup", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.nocleanup, + "don't clean up the database after indexing (false)", + NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("index", "Options for the 'index' command", - "", NULL, NULL); + og = g_option_group_new("index", "Options for the 'index' command", "", NULL, NULL); g_option_group_add_entries(og, entries); - g_option_group_set_parse_hooks(og, NULL, (GOptionParseFunc)index_post_parse_func); + g_option_group_set_parse_hooks(og, NULL, (GOptionParseFunc)index_post_parse_func); return og; } static void -set_group_find_defaults () +set_group_find_defaults() { /* note, when no fields are specified, we use date-from-subject */ if (!MU_CONFIG.fields || !*MU_CONFIG.fields) { - MU_CONFIG.fields = g_strdup ("d f s"); + MU_CONFIG.fields = g_strdup("d f s"); if (!MU_CONFIG.sortfield) { - MU_CONFIG.sortfield = g_strdup ("d"); + MU_CONFIG.sortfield = g_strdup("d"); } } if (!MU_CONFIG.formatstr) /* by default, use plain output */ MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; else - MU_CONFIG.format = - get_output_format (MU_CONFIG.formatstr); + MU_CONFIG.format = get_output_format(MU_CONFIG.formatstr); - expand_dir (MU_CONFIG.linksdir); + expand_dir(MU_CONFIG.linksdir); } static GOptionGroup* -config_options_group_find () +config_options_group_find() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"fields", 'f', 0, G_OPTION_ARG_STRING, &MU_CONFIG.fields, - "fields to display in the output", ""}, - {"sortfield", 's', 0, G_OPTION_ARG_STRING, - &MU_CONFIG.sortfield, - "field to sort on", ""}, - {"maxnum", 'n', 0, G_OPTION_ARG_INT, &MU_CONFIG.maxnum, - "number of entries to display in the output", ""}, - {"threads", 't', 0, G_OPTION_ARG_NONE, &MU_CONFIG.threads, - "show message threads", NULL}, - {"bookmark", 'b', 0, G_OPTION_ARG_STRING, &MU_CONFIG.bookmark, - "use a bookmarked query", ""}, - {"reverse", 'z', 0, G_OPTION_ARG_NONE, &MU_CONFIG.reverse, - "sort in reverse (descending) order (z -> a)", NULL}, - {"skip-dups", 'u', 0, G_OPTION_ARG_NONE, - &MU_CONFIG.skip_dups, - "show only the first of messages duplicates (false)", NULL}, - {"include-related", 'r', 0, G_OPTION_ARG_NONE, - &MU_CONFIG.include_related, - "include related messages in results (false)", NULL}, - {"linksdir", 0, 0, G_OPTION_ARG_STRING, &MU_CONFIG.linksdir, - "output as symbolic links to a target maildir", ""}, - {"clearlinks", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.clearlinks, - "clear old links before filling a linksdir (false)", NULL}, - {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, - "output format ('plain'(*), 'links', 'xml'," - "'sexp', 'xquery')", ""}, - {"summary-len", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.summary_len, - "use up to lines for the summary, or 0 for none (0)", - ""}, - {"exec", 'e', 0, G_OPTION_ARG_STRING, &MU_CONFIG.exec, - "execute command on each match message", ""}, - {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, - "only show messages whose m_time > T (t_time)", - ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"fields", + 'f', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.fields, + "fields to display in the output", + ""}, + {"sortfield", + 's', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.sortfield, + "field to sort on", + ""}, + {"maxnum", + 'n', + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.maxnum, + "number of entries to display in the output", + ""}, + {"threads", + 't', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.threads, + "show message threads", + NULL}, + {"bookmark", + 'b', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.bookmark, + "use a bookmarked query", + ""}, + {"reverse", + 'z', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.reverse, + "sort in reverse (descending) order (z -> a)", + NULL}, + {"skip-dups", + 'u', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.skip_dups, + "show only the first of messages duplicates (false)", + NULL}, + {"include-related", + 'r', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.include_related, + "include related messages in results (false)", + NULL}, + {"linksdir", + 0, + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.linksdir, + "output as symbolic links to a target maildir", + ""}, + {"clearlinks", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.clearlinks, + "clear old links before filling a linksdir (false)", + NULL}, + {"format", + 'o', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.formatstr, + "output format ('plain'(*), 'links', 'xml'," + "'sexp', 'xquery')", + ""}, + {"summary-len", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.summary_len, + "use up to lines for the summary, or 0 for none (0)", + ""}, + {"exec", + 'e', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.exec, + "execute command on each match message", + ""}, + {"after", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.after, + "only show messages whose m_time > T (t_time)", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("find", - "Options for the 'find' command", - "", NULL, NULL); + og = g_option_group_new("find", "Options for the 'find' command", "", NULL, NULL); g_option_group_add_entries(og, entries); return og; } -static GOptionGroup * -config_options_group_mkdir () +static GOptionGroup* +config_options_group_mkdir() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"mode", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.dirmode, - "set the mode (as in chmod), in octal notation", ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"mode", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.dirmode, + "set the mode (as in chmod), in octal notation", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; /* set dirmode before, because '0000' is a valid mode */ MU_CONFIG.dirmode = 0755; - og = g_option_group_new("mkdir", "Options for the 'mkdir' command", - "", NULL, NULL); + og = g_option_group_new("mkdir", "Options for the 'mkdir' command", "", NULL, NULL); g_option_group_add_entries(og, entries); return og; } static void -set_group_cfind_defaults () +set_group_cfind_defaults() { if (!MU_CONFIG.formatstr) /* by default, use plain output */ MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; else - MU_CONFIG.format = get_output_format (MU_CONFIG.formatstr); + MU_CONFIG.format = get_output_format(MU_CONFIG.formatstr); } -static GOptionGroup * -config_options_group_cfind () +static GOptionGroup* +config_options_group_cfind() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, - "output format (plain(*), mutt-alias, mutt-ab, wl, " - "org-contact, bbdb, csv)", ""}, - {"personal", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.personal, - "whether to only get 'personal' contacts", NULL}, - {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, - "only get addresses last seen after T", ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"format", + 'o', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.formatstr, + "output format (plain(*), mutt-alias, mutt-ab, wl, " + "org-contact, bbdb, csv)", + ""}, + {"personal", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.personal, + "whether to only get 'personal' contacts", + NULL}, + {"after", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.after, + "only get addresses last seen after T", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("cfind", "Options for the 'cfind' command", - "", NULL, NULL); + og = g_option_group_new("cfind", "Options for the 'cfind' command", "", NULL, NULL); g_option_group_add_entries(og, entries); return og; } -static GOptionGroup * -config_options_group_script () +static GOptionGroup* +config_options_group_script() { - GOptionGroup *og; - GOptionEntry entries[] = { - {G_OPTION_REMAINING, 0,0, G_OPTION_ARG_STRING_ARRAY, - &MU_CONFIG.params, "script parameters", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{G_OPTION_REMAINING, + 0, + 0, + G_OPTION_ARG_STRING_ARRAY, + &MU_CONFIG.params, + "script parameters", + NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("script", "Options for the 'script' command", - "", NULL, NULL); + og = g_option_group_new("script", "Options for the 'script' command", "", NULL, NULL); g_option_group_add_entries(og, entries); @@ -344,51 +483,72 @@ config_options_group_script () } static void -set_group_view_defaults () +set_group_view_defaults() { if (!MU_CONFIG.formatstr) /* by default, use plain output */ MU_CONFIG.format = MU_CONFIG_FORMAT_PLAIN; else - MU_CONFIG.format = get_output_format (MU_CONFIG.formatstr); + MU_CONFIG.format = get_output_format(MU_CONFIG.formatstr); } - /* crypto options are used in a few different commands */ static GOptionEntry* -crypto_option_entries () +crypto_option_entries() { - static GOptionEntry entries[] = { - {"auto-retrieve", 'r', 0, G_OPTION_ARG_NONE, - &MU_CONFIG.auto_retrieve, - "attempt to retrieve keys online (false)", NULL}, - {"use-agent", 'a', 0, G_OPTION_ARG_NONE, &MU_CONFIG.use_agent, - "attempt to use the GPG agent (false)", NULL}, - {"decrypt", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.decrypt, - "attempt to decrypt the message", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + static GOptionEntry entries[] = {{"auto-retrieve", + 'r', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.auto_retrieve, + "attempt to retrieve keys online (false)", + NULL}, + {"use-agent", + 'a', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.use_agent, + "attempt to use the GPG agent (false)", + NULL}, + {"decrypt", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.decrypt, + "attempt to decrypt the message", + NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; return entries; } -static GOptionGroup * -config_options_group_view () +static GOptionGroup* +config_options_group_view() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"summary-len", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.summary_len, - "use up to lines for the summary, or 0 for none (0)", - ""}, - {"terminate", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.terminator, - "terminate messages with ascii-0x07 (\\f, form-feed)", - ""}, - {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, - "output format ('plain'(*), 'sexp')", ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"summary-len", + 0, + 0, + G_OPTION_ARG_INT, + &MU_CONFIG.summary_len, + "use up to lines for the summary, or 0 for none (0)", + ""}, + {"terminate", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.terminator, + "terminate messages with ascii-0x07 (\\f, form-feed)", + ""}, + {"format", + 'o', + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.formatstr, + "output format ('plain'(*), 'sexp')", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("view", "Options for the 'view' command", - "", NULL, NULL); + og = g_option_group_new("view", "Options for the 'view' command", "", NULL, NULL); g_option_group_add_entries(og, entries); g_option_group_add_entries(og, crypto_option_entries()); @@ -397,110 +557,132 @@ config_options_group_view () } static void -set_group_extract_defaults () +set_group_extract_defaults() { if (!MU_CONFIG.targetdir) - MU_CONFIG.targetdir = g_strdup ("."); + MU_CONFIG.targetdir = g_strdup("."); - expand_dir (MU_CONFIG.targetdir); + expand_dir(MU_CONFIG.targetdir); } - static GOptionGroup* -config_options_group_extract () +config_options_group_extract() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"save-attachments", 'a', 0, G_OPTION_ARG_NONE, - &MU_CONFIG.save_attachments, - "save all attachments (false)", NULL}, - {"save-all", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.save_all, - "save all parts (incl. non-attachments) (false)", NULL}, - {"parts", 0, 0, G_OPTION_ARG_STRING, &MU_CONFIG.parts, - "save specific parts (comma-separated list)", ""}, - {"target-dir", 0, 0, G_OPTION_ARG_FILENAME, - &MU_CONFIG.targetdir, - "target directory for saving", ""}, - {"overwrite", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.overwrite, - "overwrite existing files (false)", NULL}, - {"play", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.play, - "try to 'play' (open) the extracted parts", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; - og = g_option_group_new("extract", - "Options for the 'extract' command", - "", NULL, NULL); + GOptionGroup* og; + GOptionEntry entries[] = {{"save-attachments", + 'a', + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.save_attachments, + "save all attachments (false)", + NULL}, + {"save-all", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.save_all, + "save all parts (incl. non-attachments) (false)", + NULL}, + {"parts", + 0, + 0, + G_OPTION_ARG_STRING, + &MU_CONFIG.parts, + "save specific parts (comma-separated list)", + ""}, + {"target-dir", + 0, + 0, + G_OPTION_ARG_FILENAME, + &MU_CONFIG.targetdir, + "target directory for saving", + ""}, + {"overwrite", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.overwrite, + "overwrite existing files (false)", + NULL}, + {"play", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.play, + "try to 'play' (open) the extracted parts", + NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; + og = g_option_group_new("extract", "Options for the 'extract' command", "", NULL, NULL); g_option_group_add_entries(og, entries); g_option_group_add_entries(og, crypto_option_entries()); return og; } - static GOptionGroup* -config_options_group_verify () +config_options_group_verify() { - GOptionGroup *og; - og = g_option_group_new("verify", - "Options for the 'verify' command", - "", NULL, NULL); + GOptionGroup* og; + og = g_option_group_new("verify", "Options for the 'verify' command", "", NULL, NULL); g_option_group_add_entries(og, crypto_option_entries()); return og; } - static GOptionGroup* -config_options_group_server () +config_options_group_server() { - GOptionGroup *og; - GOptionEntry entries[] = { - {"commands", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.commands, - "list the available command and their parameters, then exit", NULL}, - {"eval", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &MU_CONFIG.eval, "expression to evaluate", ""}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} - }; + GOptionGroup* og; + GOptionEntry entries[] = {{"commands", + 0, + 0, + G_OPTION_ARG_NONE, + &MU_CONFIG.commands, + "list the available command and their parameters, then exit", + NULL}, + {"eval", + 'e', + G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_STRING, + &MU_CONFIG.eval, + "expression to evaluate", + ""}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - og = g_option_group_new("server", - "Options for the 'server' command", - "", NULL, NULL); + og = g_option_group_new("server", "Options for the 'server' command", "", NULL, NULL); g_option_group_add_entries(og, entries); return og; } - static MuConfigCmd -cmd_from_string (const char *str) +cmd_from_string(const char* str) { int i; struct { - const gchar* name; - MuConfigCmd cmd; - } cmd_map[] = { - { "add", MU_CONFIG_CMD_ADD }, - { "cfind", MU_CONFIG_CMD_CFIND }, - { "extract", MU_CONFIG_CMD_EXTRACT }, - { "find", MU_CONFIG_CMD_FIND }, - { "help", MU_CONFIG_CMD_HELP }, - { "index", MU_CONFIG_CMD_INDEX }, - { "info", MU_CONFIG_CMD_INFO }, - { "init", MU_CONFIG_CMD_INIT }, - { "mkdir", MU_CONFIG_CMD_MKDIR }, - { "remove", MU_CONFIG_CMD_REMOVE }, - { "script", MU_CONFIG_CMD_SCRIPT }, - { "server", MU_CONFIG_CMD_SERVER }, - { "tickle", MU_CONFIG_CMD_TICKLE }, - { "verify", MU_CONFIG_CMD_VERIFY }, - { "view", MU_CONFIG_CMD_VIEW } - }; + const gchar* name; + MuConfigCmd cmd; + } cmd_map[] = {{"add", MU_CONFIG_CMD_ADD}, + {"cfind", MU_CONFIG_CMD_CFIND}, + {"extract", MU_CONFIG_CMD_EXTRACT}, + {"find", MU_CONFIG_CMD_FIND}, + {"help", MU_CONFIG_CMD_HELP}, + {"index", MU_CONFIG_CMD_INDEX}, + {"info", MU_CONFIG_CMD_INFO}, + {"init", MU_CONFIG_CMD_INIT}, + {"mkdir", MU_CONFIG_CMD_MKDIR}, + {"remove", MU_CONFIG_CMD_REMOVE}, + {"script", MU_CONFIG_CMD_SCRIPT}, + {"server", MU_CONFIG_CMD_SERVER}, + {"tickle", MU_CONFIG_CMD_TICKLE}, + {"verify", MU_CONFIG_CMD_VERIFY}, + {"view", MU_CONFIG_CMD_VIEW}}; if (!str) return MU_CONFIG_CMD_UNKNOWN; for (i = 0; i != G_N_ELEMENTS(cmd_map); ++i) - if (strcmp (str, cmd_map[i].name) == 0) + if (strcmp(str, cmd_map[i].name) == 0) return cmd_map[i].cmd; #ifdef BUILD_GUILE /* if we don't recognize it and it's not an option, it may be @@ -512,12 +694,10 @@ cmd_from_string (const char *str) return MU_CONFIG_CMD_UNKNOWN; } - - static gboolean -parse_cmd (int *argcp, char ***argvp, GError **err) +parse_cmd(int* argcp, char*** argvp, GError** err) { - MU_CONFIG.cmd = MU_CONFIG_CMD_NONE; + MU_CONFIG.cmd = MU_CONFIG_CMD_NONE; MU_CONFIG.cmdstr = NULL; if (*argcp < 2) /* no command found at all */ @@ -528,83 +708,64 @@ parse_cmd (int *argcp, char ***argvp, GError **err) * etc.)*/ return TRUE; - MU_CONFIG.cmdstr = g_strdup ((*argvp)[1]); - MU_CONFIG.cmd = cmd_from_string (MU_CONFIG.cmdstr); + MU_CONFIG.cmdstr = g_strdup((*argvp)[1]); + MU_CONFIG.cmd = cmd_from_string(MU_CONFIG.cmdstr); #ifndef BUILD_GUILE if (MU_CONFIG.cmd == MU_CONFIG_CMD_SCRIPT) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "command 'script' not supported"); + mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "command 'script' not supported"); return FALSE; } #endif /*!BUILD_GUILE*/ if (MU_CONFIG.cmdstr && MU_CONFIG.cmdstr[0] != '-' && MU_CONFIG.cmd == MU_CONFIG_CMD_UNKNOWN) { - mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, - "unknown command '%s'", - MU_CONFIG.cmdstr); + mu_util_g_set_error(err, + MU_ERROR_IN_PARAMETERS, + "unknown command '%s'", + MU_CONFIG.cmdstr); return FALSE; } return TRUE; } - static GOptionGroup* -get_option_group (MuConfigCmd cmd) +get_option_group(MuConfigCmd cmd) { switch (cmd) { - case MU_CONFIG_CMD_CFIND: - return config_options_group_cfind(); - case MU_CONFIG_CMD_EXTRACT: - return config_options_group_extract(); - case MU_CONFIG_CMD_FIND: - return config_options_group_find(); - case MU_CONFIG_CMD_INDEX: - return config_options_group_index(); - case MU_CONFIG_CMD_INIT: - return config_options_group_init(); - case MU_CONFIG_CMD_MKDIR: - return config_options_group_mkdir(); - case MU_CONFIG_CMD_SERVER: - return config_options_group_server(); - case MU_CONFIG_CMD_SCRIPT: - return config_options_group_script(); - case MU_CONFIG_CMD_VERIFY: - return config_options_group_verify(); - case MU_CONFIG_CMD_VIEW: - return config_options_group_view(); - default: - return NULL; /* no group to add */ + case MU_CONFIG_CMD_CFIND: return config_options_group_cfind(); + case MU_CONFIG_CMD_EXTRACT: return config_options_group_extract(); + case MU_CONFIG_CMD_FIND: return config_options_group_find(); + case MU_CONFIG_CMD_INDEX: return config_options_group_index(); + case MU_CONFIG_CMD_INIT: return config_options_group_init(); + case MU_CONFIG_CMD_MKDIR: return config_options_group_mkdir(); + case MU_CONFIG_CMD_SERVER: return config_options_group_server(); + case MU_CONFIG_CMD_SCRIPT: return config_options_group_script(); + case MU_CONFIG_CMD_VERIFY: return config_options_group_verify(); + case MU_CONFIG_CMD_VIEW: return config_options_group_view(); + default: return NULL; /* no group to add */ } } - - /* ugh yuck massaging the GOption text output; glib prepares some text * which has a 'Usage:' for the 'help' command. However, we need the * help for the command we're asking help for. So, we remove the Usage: * from what glib generates. :-( */ static gchar* -massage_help (const char *help) +massage_help(const char* help) { - GRegex *rx; - char *str; + GRegex* rx; + char* str; - rx = g_regex_new ("^Usage:.*\n.*\n", - (GRegexCompileFlags)0, G_REGEX_MATCH_NEWLINE_ANY, NULL); - str = g_regex_replace (rx, help, - -1, 0, "", - G_REGEX_MATCH_NEWLINE_ANY, NULL); - g_regex_unref (rx); + rx = g_regex_new("^Usage:.*\n.*\n", (GRegexCompileFlags)0, G_REGEX_MATCH_NEWLINE_ANY, NULL); + str = g_regex_replace(rx, help, -1, 0, "", G_REGEX_MATCH_NEWLINE_ANY, NULL); + g_regex_unref(rx); return str; } - - static const gchar* -get_help_string (MuConfigCmd cmd, gboolean long_help) +get_help_string(MuConfigCmd cmd, gboolean long_help) { unsigned u; @@ -616,120 +777,115 @@ get_help_string (MuConfigCmd cmd, gboolean long_help) if (long_help) return MU_HELP_STRINGS[u].long_help; else - return MU_HELP_STRINGS[u].usage ; + return MU_HELP_STRINGS[u].usage; } - g_return_val_if_reached (""); + g_return_val_if_reached(""); return ""; } - void -Mu::mu_config_show_help (MuConfigCmd cmd) +Mu::mu_config_show_help(MuConfigCmd cmd) { - GOptionContext *ctx; - GOptionGroup *group; - char *help, *cleanhelp; + GOptionContext* ctx; + GOptionGroup* group; + char * help, *cleanhelp; - g_return_if_fail (mu_config_cmd_is_valid(cmd)); + g_return_if_fail(mu_config_cmd_is_valid(cmd)); - ctx = g_option_context_new ("- mu help"); - g_option_context_set_main_group (ctx, config_options_group_mu()); + ctx = g_option_context_new("- mu help"); + g_option_context_set_main_group(ctx, config_options_group_mu()); - group = get_option_group (cmd); + group = get_option_group(cmd); if (group) - g_option_context_add_group (ctx, group); + g_option_context_add_group(ctx, group); - g_option_context_set_description (ctx, get_help_string (cmd, TRUE)); - help = g_option_context_get_help (ctx, TRUE, group); - cleanhelp = massage_help (help); + g_option_context_set_description(ctx, get_help_string(cmd, TRUE)); + help = g_option_context_get_help(ctx, TRUE, group); + cleanhelp = massage_help(help); - g_print ("usage:\n\t%s%s", - get_help_string (cmd, FALSE), cleanhelp); + g_print("usage:\n\t%s%s", get_help_string(cmd, FALSE), cleanhelp); - g_free (help); - g_free (cleanhelp); - g_option_context_free (ctx); + g_free(help); + g_free(cleanhelp); + g_option_context_free(ctx); } static gboolean -cmd_help () +cmd_help() { MuConfigCmd cmd; if (!MU_CONFIG.params) cmd = MU_CONFIG_CMD_UNKNOWN; else - cmd = cmd_from_string (MU_CONFIG.params[1]); + cmd = cmd_from_string(MU_CONFIG.params[1]); if (cmd == MU_CONFIG_CMD_UNKNOWN) { - mu_config_show_help (MU_CONFIG_CMD_HELP); + mu_config_show_help(MU_CONFIG_CMD_HELP); return TRUE; } - mu_config_show_help (cmd); + mu_config_show_help(cmd); return TRUE; } static gboolean -parse_params (int *argcp, char ***argvp, GError **err) +parse_params(int* argcp, char*** argvp, GError** err) { - GOptionContext *context; - GOptionGroup *group; - gboolean rv; + GOptionContext* context; + GOptionGroup* group; + gboolean rv; context = g_option_context_new("- mu general options"); - g_option_context_set_help_enabled (context, TRUE); - rv = TRUE; + g_option_context_set_help_enabled(context, TRUE); + rv = TRUE; - g_option_context_set_main_group(context, - config_options_group_mu()); - g_option_context_set_ignore_unknown_options (context, FALSE); + g_option_context_set_main_group(context, config_options_group_mu()); + g_option_context_set_ignore_unknown_options(context, FALSE); switch (MU_CONFIG.cmd) { case MU_CONFIG_CMD_NONE: case MU_CONFIG_CMD_HELP: /* 'help' is special; sucks in the options of the * command after it */ - rv = g_option_context_parse (context, argcp, argvp, err) && - cmd_help (); + rv = g_option_context_parse(context, argcp, argvp, err) && cmd_help(); break; case MU_CONFIG_CMD_SCRIPT: /* all unknown commands are passed to 'script' */ - g_option_context_set_ignore_unknown_options (context, TRUE); - group = get_option_group (MU_CONFIG.cmd); - g_option_context_add_group (context, group); - rv = g_option_context_parse (context, argcp, argvp, err); - MU_CONFIG.script = g_strdup (MU_CONFIG.cmdstr); + g_option_context_set_ignore_unknown_options(context, TRUE); + group = get_option_group(MU_CONFIG.cmd); + g_option_context_add_group(context, group); + rv = g_option_context_parse(context, argcp, argvp, err); + MU_CONFIG.script = g_strdup(MU_CONFIG.cmdstr); /* argvp contains the script parameters */ MU_CONFIG.script_params = (const char**)&((*argvp)[1]); break; default: - group = get_option_group (MU_CONFIG.cmd); + group = get_option_group(MU_CONFIG.cmd); if (group) - g_option_context_add_group (context, group); + g_option_context_add_group(context, group); - rv = g_option_context_parse (context, argcp, argvp, err); + rv = g_option_context_parse(context, argcp, argvp, err); break; } - g_option_context_free (context); + g_option_context_free(context); return rv ? TRUE : FALSE; } - MuConfig* -Mu::mu_config_init (int *argcp, char ***argvp, GError **err) +Mu::mu_config_init(int* argcp, char*** argvp, GError** err) { - g_return_val_if_fail (argcp && argvp, NULL); + g_return_val_if_fail(argcp && argvp, NULL); - memset (&MU_CONFIG, 0, sizeof(MU_CONFIG)); + memset(&MU_CONFIG, 0, sizeof(MU_CONFIG)); - if (!parse_cmd (argcp, argvp, err)) + if (!parse_cmd(argcp, argvp, err)) goto errexit; if (!parse_params(argcp, argvp, err)) @@ -747,50 +903,49 @@ Mu::mu_config_init (int *argcp, char ***argvp, GError **err) return &MU_CONFIG; errexit: - mu_config_uninit (&MU_CONFIG); + mu_config_uninit(&MU_CONFIG); return NULL; } - void -Mu::mu_config_uninit (MuConfig *opts) +Mu::mu_config_uninit(MuConfig* opts) { if (!opts) return; - g_free (opts->cmdstr); - g_free (opts->muhome); - g_free (opts->maildir); - g_free (opts->fields); - g_free (opts->sortfield); - g_free (opts->bookmark); - g_free (opts->formatstr); - g_free (opts->exec); - g_free (opts->linksdir); - g_free (opts->targetdir); - g_free (opts->parts); - g_free (opts->script); - g_free (opts->eval); + g_free(opts->cmdstr); + g_free(opts->muhome); + g_free(opts->maildir); + g_free(opts->fields); + g_free(opts->sortfield); + g_free(opts->bookmark); + g_free(opts->formatstr); + g_free(opts->exec); + g_free(opts->linksdir); + g_free(opts->targetdir); + g_free(opts->parts); + g_free(opts->script); + g_free(opts->eval); - g_strfreev (opts->params); + g_strfreev(opts->params); - memset (opts, 0, sizeof(MU_CONFIG)); + memset(opts, 0, sizeof(MU_CONFIG)); } size_t -Mu::mu_config_param_num (const MuConfig *opts) +Mu::mu_config_param_num(const MuConfig* opts) { size_t n; - g_return_val_if_fail (opts && opts->params, 0); - for (n = 0; opts->params[n]; ++n); + g_return_val_if_fail(opts && opts->params, 0); + for (n = 0; opts->params[n]; ++n) + ; return n; } - MuMsgOptions -Mu::mu_config_get_msg_options (const MuConfig *muopts) +Mu::mu_config_get_msg_options(const MuConfig* muopts) { int opts; diff --git a/mu/mu-config.hh b/mu/mu-config.hh index 93c465bf..2a9ada74 100644 --- a/mu/mu-config.hh +++ b/mu/mu-config.hh @@ -35,28 +35,28 @@ typedef enum { MU_CONFIG_FORMAT_UNKNOWN = 0, /* for cfind, find, view */ - MU_CONFIG_FORMAT_PLAIN, /* plain output */ + MU_CONFIG_FORMAT_PLAIN, /* plain output */ /* for cfind */ - MU_CONFIG_FORMAT_MUTT_ALIAS, /* mutt alias style */ - MU_CONFIG_FORMAT_MUTT_AB, /* mutt ext abook */ - MU_CONFIG_FORMAT_WL, /* Wanderlust abook */ - MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */ - MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */ - MU_CONFIG_FORMAT_BBDB, /* BBDB */ + MU_CONFIG_FORMAT_MUTT_ALIAS, /* mutt alias style */ + MU_CONFIG_FORMAT_MUTT_AB, /* mutt ext abook */ + MU_CONFIG_FORMAT_WL, /* Wanderlust abook */ + MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */ + MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */ + MU_CONFIG_FORMAT_BBDB, /* BBDB */ MU_CONFIG_FORMAT_DEBUG, /* for find, view */ - MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */ - MU_CONFIG_FORMAT_JSON, /* output JSON */ + MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */ + MU_CONFIG_FORMAT_JSON, /* output JSON */ /* for find */ - MU_CONFIG_FORMAT_LINKS, /* output as symlinks */ - MU_CONFIG_FORMAT_XML, /* output xml */ - MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */ - MU_CONFIG_FORMAT_MQUERY, /* output the mux query */ + MU_CONFIG_FORMAT_LINKS, /* output as symlinks */ + MU_CONFIG_FORMAT_XML, /* output xml */ + MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */ + MU_CONFIG_FORMAT_MQUERY, /* output the mux query */ - MU_CONFIG_FORMAT_EXEC /* execute some command */ + MU_CONFIG_FORMAT_EXEC /* execute some command */ } MuConfigFormat; typedef enum { @@ -68,8 +68,8 @@ typedef enum { MU_CONFIG_CMD_FIND, MU_CONFIG_CMD_HELP, MU_CONFIG_CMD_INDEX, - MU_CONFIG_CMD_INFO, - MU_CONFIG_CMD_INIT, + MU_CONFIG_CMD_INFO, + MU_CONFIG_CMD_INIT, MU_CONFIG_CMD_MKDIR, MU_CONFIG_CMD_REMOVE, MU_CONFIG_CMD_SCRIPT, @@ -81,115 +81,110 @@ typedef enum { MU_CONFIG_CMD_NONE } MuConfigCmd; - -#define mu_config_cmd_is_valid(C) \ - ((C) > MU_CONFIG_CMD_UNKNOWN && (C) < MU_CONFIG_CMD_NONE) - +#define mu_config_cmd_is_valid(C) ((C) > MU_CONFIG_CMD_UNKNOWN && (C) < MU_CONFIG_CMD_NONE) /* struct with all configuration options for mu; it will be filled * from the config file, and/or command line arguments */ struct _MuConfig { - - MuConfigCmd cmd; /* the command, or - * MU_CONFIG_CMD_NONE */ - char *cmdstr; /* cmd string, for user - * info */ + MuConfigCmd cmd; /* the command, or + * MU_CONFIG_CMD_NONE */ + char* cmdstr; /* cmd string, for user + * info */ /* general options */ - gboolean quiet; /* don't give any output */ - gboolean debug; /* log debug-level info */ - gchar *muhome; /* the House of Mu */ - gboolean version; /* request mu version */ - gboolean log_stderr; /* log to stderr (not logfile) */ - gchar** params; /* parameters (for querying) */ - gboolean nocolor; /* don't use use ansi-colors - * in some output */ - gboolean verbose; /* verbose output */ + gboolean quiet; /* don't give any output */ + gboolean debug; /* log debug-level info */ + gchar* muhome; /* the House of Mu */ + gboolean version; /* request mu version */ + gboolean log_stderr; /* log to stderr (not logfile) */ + gchar** params; /* parameters (for querying) */ + gboolean nocolor; /* don't use use ansi-colors + * in some output */ + gboolean verbose; /* verbose output */ - /* options for init */ - gchar *maildir; /* where the mails are */ - char** my_addresses; /* 'my e-mail address', for mu cfind; - * can be use multiple times */ - int max_msg_size; /* maximum size for message files */ - int batch_size; /* database transaction batch size */ + /* options for init */ + gchar* maildir; /* where the mails are */ + char** my_addresses; /* 'my e-mail address', for mu cfind; + * can be use multiple times */ + int max_msg_size; /* maximum size for message files */ + int batch_size; /* database transaction batch size */ /* options for indexing */ - gboolean nocleanup; /* don't cleanup del'd mails from db */ - gboolean rebuild; /* empty the database before indexing */ - gboolean lazycheck; /* don't check dirs with up-to-date - * timestamps */ - + gboolean nocleanup; /* don't cleanup del'd mails from db */ + gboolean rebuild; /* empty the database before indexing */ + gboolean lazycheck; /* don't check dirs with up-to-date + * timestamps */ /* options for querying 'find' (and view-> 'summary') */ - gchar *fields; /* fields to show in output */ - gchar *sortfield; /* field to sort by (string) */ - int maxnum; /* max # of entries to print */ - gboolean reverse; /* sort in revers order (z->a) */ - gboolean threads; /* show message threads */ + gchar* fields; /* fields to show in output */ + gchar* sortfield; /* field to sort by (string) */ + int maxnum; /* max # of entries to print */ + gboolean reverse; /* sort in revers order (z->a) */ + gboolean threads; /* show message threads */ - gboolean summary; /* OBSOLETE: use summary_len */ - int summary_len; /* max # of lines for summary */ + gboolean summary; /* OBSOLETE: use summary_len */ + int summary_len; /* max # of lines for summary */ - gchar *bookmark; /* use bookmark */ - gchar *formatstr; /* output type for find - * (plain,links,xml,json,sexp) - * and view (plain, sexp) and cfind - */ - MuConfigFormat format; /* the decoded formatstr */ - gchar *exec; /* command to execute on the - * files for the matched - * messages */ - gboolean skip_dups; /* if there are multiple - * messages with the same - * msgid, show only the first - * one */ - gboolean include_related; /* included related messages - * in results */ + gchar* bookmark; /* use bookmark */ + gchar* formatstr; /* output type for find + * (plain,links,xml,json,sexp) + * and view (plain, sexp) and cfind + */ + MuConfigFormat format; /* the decoded formatstr */ + gchar* exec; /* command to execute on the + * files for the matched + * messages */ + gboolean skip_dups; /* if there are multiple + * messages with the same + * msgid, show only the first + * one */ + gboolean include_related; /* included related messages + * in results */ /* for find and cind */ - time_t after; /* only show messages or - * addresses last seen after - * T */ + time_t after; /* only show messages or + * addresses last seen after + * T */ /* options for crypto * ie, 'view', 'extract' */ - gboolean auto_retrieve; /* assume we're online */ - gboolean use_agent; /* attempt to use the gpg-agent */ - gboolean decrypt; /* try to decrypt the - * message body, if any */ - gboolean verify; /* try to crypto-verify the - * message */ + gboolean auto_retrieve; /* assume we're online */ + gboolean use_agent; /* attempt to use the gpg-agent */ + gboolean decrypt; /* try to decrypt the + * message body, if any */ + gboolean verify; /* try to crypto-verify the + * message */ /* options for view */ - gboolean terminator; /* add separator \f between - * multiple messages in mu - * view */ + gboolean terminator; /* add separator \f between + * multiple messages in mu + * view */ /* options for cfind (and 'find' --> "after") */ - gboolean personal; /* only show 'personal' addresses */ + gboolean personal; /* only show 'personal' addresses */ /* also 'after' --> see above */ /* output to a maildir with symlinks */ - gchar *linksdir; /* maildir to output symlinks */ - gboolean clearlinks; /* clear a linksdir before filling */ - mode_t dirmode; /* mode for the created maildir */ + gchar* linksdir; /* maildir to output symlinks */ + gboolean clearlinks; /* clear a linksdir before filling */ + mode_t dirmode; /* mode for the created maildir */ /* options for extracting parts */ - gboolean save_all; /* extract all parts */ - gboolean save_attachments; /* extract all attachment parts */ - gchar *parts; /* comma-sep'd list of parts - * to save / open */ - gchar *targetdir; /* where to save the attachments */ - gboolean overwrite; /* should we overwrite same-named files */ - gboolean play; /* after saving, try to 'play' - * (open) the attmnt using xdgopen */ + gboolean save_all; /* extract all parts */ + gboolean save_attachments; /* extract all attachment parts */ + gchar* parts; /* comma-sep'd list of parts + * to save / open */ + gchar* targetdir; /* where to save the attachments */ + gboolean overwrite; /* should we overwrite same-named files */ + gboolean play; /* after saving, try to 'play' + * (open) the attmnt using xdgopen */ /* for server */ - gboolean commands; /* dump documentations for server - * commands */ - gchar *eval; /* command to evaluate */ + gboolean commands; /* dump documentations for server + * commands */ + gchar* eval; /* command to evaluate */ - /* options for mu-script */ - gchar *script; /* script to run */ - const char **script_params; /* parameters for scripts */ + /* options for mu-script */ + gchar* script; /* script to run */ + const char** script_params; /* parameters for scripts */ }; typedef struct _MuConfig MuConfig; @@ -207,15 +202,13 @@ typedef struct _MuConfig MuConfig; * @param argvp: pointer to argv * @param err: receives error information */ -MuConfig *mu_config_init (int *argcp, char ***argvp, GError **err) - G_GNUC_WARN_UNUSED_RESULT; +MuConfig* mu_config_init(int* argcp, char*** argvp, GError** err) G_GNUC_WARN_UNUSED_RESULT; /** * free the MuConfig structure * * @param opts a MuConfig struct, or NULL */ -void mu_config_uninit (MuConfig *conf); - +void mu_config_uninit(MuConfig* conf); /** * execute the command / options in this config @@ -227,7 +220,7 @@ void mu_config_uninit (MuConfig *conf); * the exit code of the process * */ -MuError mu_config_execute (const MuConfig *conf); +MuError mu_config_execute(const MuConfig* conf); /** * count the number of non-option parameters @@ -236,8 +229,7 @@ MuError mu_config_execute (const MuConfig *conf); * * @return the number of non-option parameters, or 0 in case of error */ -size_t mu_config_param_num (const MuConfig *conf); - +size_t mu_config_param_num(const MuConfig* conf); /** * determine MuMsgOptions for command line args @@ -246,15 +238,14 @@ size_t mu_config_param_num (const MuConfig *conf); * * @return the corresponding MuMsgOptions */ -MuMsgOptions mu_config_get_msg_options (const MuConfig *opts); - +MuMsgOptions mu_config_get_msg_options(const MuConfig* opts); /** * print help text for the current command * * @param cmd the command to show help for */ -void mu_config_show_help (const MuConfigCmd cmd); +void mu_config_show_help(const MuConfigCmd cmd); } // namespace Mu. diff --git a/mu/mu.cc b/mu/mu.cc index fb907a05..36307d04 100644 --- a/mu/mu.cc +++ b/mu/mu.cc @@ -31,110 +31,105 @@ using namespace Mu; static void -show_version (void) +show_version(void) { - const char* blurb = - "mu (mail indexer/searcher) version " VERSION "\n" - "Copyright (C) 2008-2021 Dirk-Jan C. Binnema\n" - "License GPLv3+: GNU GPL version 3 or later " - ".\n" - "This is free software: you are free to change " - "and redistribute it.\n" - "There is NO WARRANTY, to the extent permitted by law."; + const char* blurb = "mu (mail indexer/searcher) version " VERSION "\n" + "Copyright (C) 2008-2021 Dirk-Jan C. Binnema\n" + "License GPLv3+: GNU GPL version 3 or later " + ".\n" + "This is free software: you are free to change " + "and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law."; - g_print ("%s\n", blurb); + g_print("%s\n", blurb); } - static void -handle_error (MuConfig *conf, MuError merr, GError **err) +handle_error(MuConfig* conf, MuError merr, GError** err) { - if (!(err && *err)) - return; + if (!(err && *err)) + return; - using Color = MaybeAnsi::Color; - MaybeAnsi col{conf ? !conf->nocolor : false}; + using Color = MaybeAnsi::Color; + MaybeAnsi col{conf ? !conf->nocolor : false}; - if (*err) - std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": " - << col.fg(Color::BrightYellow) - << ((*err) ? (*err)->message : "something when wrong") - << "\n"; + if (*err) + std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": " + << col.fg(Color::BrightYellow) + << ((*err) ? (*err)->message : "something when wrong") << "\n"; - std::cerr << col.fg(Color::Green); + std::cerr << col.fg(Color::Green); - switch ((*err)->code) { - case MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK: - std::cerr << "Maybe mu is already running?\n"; - break; + switch ((*err)->code) { + case MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK: + std::cerr << "Maybe mu is already running?\n"; + break; - case MU_ERROR_XAPIAN_NEEDS_REINDEX: - std::cerr << "Database needs (re)indexing.\n" - << "try 'mu index' " - << "(see mu-index(1) for details)\n"; - return; - case MU_ERROR_IN_PARAMETERS: - if (conf && mu_config_cmd_is_valid(conf->cmd)) - mu_config_show_help (conf->cmd); - break; - case MU_ERROR_SCRIPT_NOT_FOUND: - std::cerr << "See the mu manpage for commands, or " - << "'mu script' for the scripts\n"; - break; - case MU_ERROR_XAPIAN_CANNOT_OPEN: - std::cerr << "Please (re)initialize mu with 'mu init' " - << "see mu-init(1) for details\n"; - return; - case MU_ERROR_XAPIAN_SCHEMA_MISMATCH: - std::cerr << "Please (re)initialize mu with 'mu init' " - << "see mu-init(1) for details\n"; - return; - default: - break; /* nothing to do */ - } + case MU_ERROR_XAPIAN_NEEDS_REINDEX: + std::cerr << "Database needs (re)indexing.\n" + << "try 'mu index' " + << "(see mu-index(1) for details)\n"; + return; + case MU_ERROR_IN_PARAMETERS: + if (conf && mu_config_cmd_is_valid(conf->cmd)) + mu_config_show_help(conf->cmd); + break; + case MU_ERROR_SCRIPT_NOT_FOUND: + std::cerr << "See the mu manpage for commands, or " + << "'mu script' for the scripts\n"; + break; + case MU_ERROR_XAPIAN_CANNOT_OPEN: + std::cerr << "Please (re)initialize mu with 'mu init' " + << "see mu-init(1) for details\n"; + return; + case MU_ERROR_XAPIAN_SCHEMA_MISMATCH: + std::cerr << "Please (re)initialize mu with 'mu init' " + << "see mu-init(1) for details\n"; + return; + default: break; /* nothing to do */ + } - std::cerr << col.reset(); + std::cerr << col.reset(); } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - GError *err; - MuError rv; - MuConfig *conf; + GError* err; + MuError rv; + MuConfig* conf; - setlocale (LC_ALL, ""); + setlocale(LC_ALL, ""); - err = NULL; - rv = MU_OK; + err = NULL; + rv = MU_OK; - conf = mu_config_init (&argc, &argv, &err); - if (!conf) { - rv = err ? (MuError)err->code : MU_ERROR; - goto cleanup; - } else if (conf->version) { - show_version (); - goto cleanup; - } + conf = mu_config_init(&argc, &argv, &err); + if (!conf) { + rv = err ? (MuError)err->code : MU_ERROR; + goto cleanup; + } else if (conf->version) { + show_version(); + goto cleanup; + } - /* nothing to do */ - if (conf->cmd == MU_CONFIG_CMD_NONE) - return 0; + /* nothing to do */ + if (conf->cmd == MU_CONFIG_CMD_NONE) + return 0; - if (!mu_runtime_init (conf->muhome, PACKAGE_NAME, conf->debug)) { - mu_config_uninit (conf); - return 1; - } + if (!mu_runtime_init(conf->muhome, PACKAGE_NAME, conf->debug)) { + mu_config_uninit(conf); + return 1; + } - rv = mu_cmd_execute (conf, &err); + rv = mu_cmd_execute(conf, &err); cleanup: - handle_error (conf, rv, &err); - g_clear_error (&err); + handle_error(conf, rv, &err); + g_clear_error(&err); - mu_config_uninit (conf); - mu_runtime_uninit (); + mu_config_uninit(conf); + mu_runtime_uninit(); - return rv; + return rv; } diff --git a/mu/test-mu-cmd-cfind.cc b/mu/test-mu-cmd-cfind.cc index 271b0607..d2a2e7d8 100644 --- a/mu/test-mu-cmd-cfind.cc +++ b/mu/test-mu-cmd-cfind.cc @@ -31,338 +31,327 @@ #include "mu-store.hh" #include "mu-query.hh" -static gchar *CONTACTS_CACHE = NULL; +static gchar* CONTACTS_CACHE = NULL; static gchar* -fill_contacts_cache (void) +fill_contacts_cache(void) { - gchar *cmdline, *tmpdir; - GError *err; + gchar * cmdline, *tmpdir; + GError* err; - tmpdir = test_mu_common_get_random_tmpdir(); - cmdline = g_strdup_printf ( - "/bin/sh -c '" - "%s init --muhome=%s --maildir=%s --quiet; " - "%s index --muhome=%s --quiet'", - MU_PROGRAM, tmpdir, MU_TESTMAILDIR, - MU_PROGRAM, tmpdir); + tmpdir = test_mu_common_get_random_tmpdir(); + cmdline = g_strdup_printf("/bin/sh -c '" + "%s init --muhome=%s --maildir=%s --quiet; " + "%s index --muhome=%s --quiet'", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR, + MU_PROGRAM, + tmpdir); if (g_test_verbose()) - g_print ("%s\n", cmdline); + g_print("%s\n", cmdline); - err = NULL; - if (!g_spawn_command_line_sync (cmdline, NULL, NULL, - NULL, &err)) { - g_printerr ("Error: %s\n", err ? err->message : "?"); - g_assert (0); + err = NULL; + if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &err)) { + g_printerr("Error: %s\n", err ? err->message : "?"); + g_assert(0); } - g_free (cmdline); + g_free(cmdline); return tmpdir; } static void -test_mu_cfind_plain (void) +test_mu_cfind_plain(void) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=plain " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=plain " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); if (g_test_verbose()) - g_print ("%s\n", cmdline); + g_print("%s\n", cmdline); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); /* note, output order is unspecified */ - g_assert (output); + g_assert(output); if (output[0] == 'H') - g_assert_cmpstr (output, - ==, - "Helmut Kröger hk@testmu.xxx\n" - "Mü testmu@testmu.xx\n"); + g_assert_cmpstr(output, + ==, + "Helmut Kröger hk@testmu.xxx\n" + "Mü testmu@testmu.xx\n"); else - g_assert_cmpstr (output, - ==, - "Mü testmu@testmu.xx\n" - "Helmut Kröger hk@testmu.xxx\n"); - g_free (cmdline); - g_free (output); - g_free (erroutput); + g_assert_cmpstr(output, + ==, + "Mü testmu@testmu.xx\n" + "Helmut Kröger hk@testmu.xxx\n"); + g_free(cmdline); + g_free(output); + g_free(erroutput); } static void -test_mu_cfind_bbdb (void) +test_mu_cfind_bbdb(void) { - gchar *cmdline, *output, *erroutput, *expected; - gchar today[12]; - struct tm *tmtoday; - time_t now; - const char *old_tz; + gchar * cmdline, *output, *erroutput, *expected; + gchar today[12]; + struct tm* tmtoday; + time_t now; + const char* old_tz; - old_tz = set_tz ("Europe/Helsinki"); + old_tz = set_tz("Europe/Helsinki"); - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=bbdb " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=bbdb " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); -#define frm1 ";; -*-coding: utf-8-emacs;-*-\n" \ - ";;; file-version: 6\n" \ - "[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \ - "((creation-date . \"%s\") " \ - "(time-stamp . \"1970-01-01\")) nil]\n" \ - "[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \ - "((creation-date . \"%s\") " \ - "(time-stamp . \"1970-01-01\")) nil]\n" +#define frm1 \ + ";; -*-coding: utf-8-emacs;-*-\n" \ + ";;; file-version: 6\n" \ + "[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \ + "((creation-date . \"%s\") " \ + "(time-stamp . \"1970-01-01\")) nil]\n" \ + "[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \ + "((creation-date . \"%s\") " \ + "(time-stamp . \"1970-01-01\")) nil]\n" +#define frm2 \ + ";; -*-coding: utf-8-emacs;-*-\n" \ + ";;; file-version: 6\n" \ + "[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \ + "((creation-date . \"%s\") " \ + "(time-stamp . \"1970-01-01\")) nil]\n" \ + "[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \ + "((creation-date . \"%s\") " \ + "(time-stamp . \"1970-01-01\")) nil]\n" -#define frm2 ";; -*-coding: utf-8-emacs;-*-\n" \ - ";;; file-version: 6\n" \ - "[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \ - "((creation-date . \"%s\") " \ - "(time-stamp . \"1970-01-01\")) nil]\n" \ - "[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \ - "((creation-date . \"%s\") " \ - "(time-stamp . \"1970-01-01\")) nil]\n" + g_assert(output); - g_assert (output); - - now = time(NULL); + now = time(NULL); tmtoday = localtime(&now); - strftime(today,sizeof(today),"%Y-%m-%d", tmtoday); + strftime(today, sizeof(today), "%Y-%m-%d", tmtoday); - expected = g_strdup_printf (output[52] == 'H' ? frm1 : frm2, - today, today); + expected = g_strdup_printf(output[52] == 'H' ? frm1 : frm2, today, today); /* g_print ("\n%s\n", output); */ - g_assert_cmpstr (output, ==, expected); + g_assert_cmpstr(output, ==, expected); - g_free (cmdline); - g_free (output); - g_free (erroutput); - g_free (expected); + g_free(cmdline); + g_free(output); + g_free(erroutput); + g_free(expected); - set_tz (old_tz); + set_tz(old_tz); } - static void -test_mu_cfind_wl (void) +test_mu_cfind_wl(void) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=wl " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=wl " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); - g_assert (output); + g_assert(output); if (output[0] == 'h') - g_assert_cmpstr (output, - ==, - "hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n" - "testmu@testmu.xx \"Mü\" \"Mü\"\n"); + g_assert_cmpstr(output, + ==, + "hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n" + "testmu@testmu.xx \"Mü\" \"Mü\"\n"); else - g_assert_cmpstr (output, - ==, - "testmu@testmu.xx \"Mü\" \"Mü\"\n" - "hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n"); + g_assert_cmpstr(output, + ==, + "testmu@testmu.xx \"Mü\" \"Mü\"\n" + "hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n"); - g_free (cmdline); - g_free (output); - g_free (erroutput); + g_free(cmdline); + g_free(output); + g_free(erroutput); } - static void -test_mu_cfind_mutt_alias (void) +test_mu_cfind_mutt_alias(void) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=mutt-alias " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=mutt-alias " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); /* both orders are possible... */ - g_assert (output); + g_assert(output); if (output[6] == 'H') - g_assert_cmpstr (output, - ==, - "alias HelmutK Helmut Kröger \n" - "alias Mü Mü \n"); + g_assert_cmpstr(output, + ==, + "alias HelmutK Helmut Kröger \n" + "alias Mü Mü \n"); else - g_assert_cmpstr (output, - ==, - "alias Mü Mü \n" - "alias HelmutK Helmut Kröger \n"); + g_assert_cmpstr(output, + ==, + "alias Mü Mü \n" + "alias HelmutK Helmut Kröger \n"); - - g_free (cmdline); - g_free (output); - g_free (erroutput); + g_free(cmdline); + g_free(output); + g_free(erroutput); } static void -test_mu_cfind_mutt_ab (void) +test_mu_cfind_mutt_ab(void) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=mutt-ab " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=mutt-ab " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); if (g_test_verbose()) g_print("%s\n", cmdline); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert (output); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert(output); if (output[39] == 'h') - g_assert_cmpstr (output, - ==, - "Matching addresses in the mu database:\n" - "hk@testmu.xxx\tHelmut Kröger\t\n" - "testmu@testmu.xx\tMü\t\n"); + g_assert_cmpstr(output, + ==, + "Matching addresses in the mu database:\n" + "hk@testmu.xxx\tHelmut Kröger\t\n" + "testmu@testmu.xx\tMü\t\n"); else - g_assert_cmpstr (output, - ==, - "Matching addresses in the mu database:\n" - "testmu@testmu.xx\tMü\t\n" - "hk@testmu.xxx\tHelmut Kröger\t\n"); + g_assert_cmpstr(output, + ==, + "Matching addresses in the mu database:\n" + "testmu@testmu.xx\tMü\t\n" + "hk@testmu.xxx\tHelmut Kröger\t\n"); - g_free (cmdline); - g_free (output); - g_free (erroutput); + g_free(cmdline); + g_free(output); + g_free(erroutput); } - static void -test_mu_cfind_org_contact (void) -{ - gchar*cmdline, *output, *erroutput; - - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=org-contact " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); - - output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - - g_assert (output); - - if (output[2] == 'H') - g_assert_cmpstr (output, - ==, - "* Helmut Kröger\n" - ":PROPERTIES:\n" - ":EMAIL: hk@testmu.xxx\n" - ":END:\n\n" - "* Mü\n" - ":PROPERTIES:\n" - ":EMAIL: testmu@testmu.xx\n" - ":END:\n\n"); - else - g_assert_cmpstr (output, - ==, - "* Mü\n" - ":PROPERTIES:\n" - ":EMAIL: testmu@testmu.xx\n" - ":END:\n\n" - "* Helmut Kröger\n" - ":PROPERTIES:\n" - ":EMAIL: hk@testmu.xxx\n" - ":END:\n\n"); - - - g_free (cmdline); - g_free (output); - g_free (erroutput); -} - - - -static void -test_mu_cfind_csv (void) +test_mu_cfind_org_contact(void) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=csv " - "'testmu\\.xxx?'", - MU_PROGRAM, CONTACTS_CACHE); + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=org-contact " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); + + output = erroutput = NULL; + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + + g_assert(output); + + if (output[2] == 'H') + g_assert_cmpstr(output, + ==, + "* Helmut Kröger\n" + ":PROPERTIES:\n" + ":EMAIL: hk@testmu.xxx\n" + ":END:\n\n" + "* Mü\n" + ":PROPERTIES:\n" + ":EMAIL: testmu@testmu.xx\n" + ":END:\n\n"); + else + g_assert_cmpstr(output, + ==, + "* Mü\n" + ":PROPERTIES:\n" + ":EMAIL: testmu@testmu.xx\n" + ":END:\n\n" + "* Helmut Kröger\n" + ":PROPERTIES:\n" + ":EMAIL: hk@testmu.xxx\n" + ":END:\n\n"); + + g_free(cmdline); + g_free(output); + g_free(erroutput); +} + +static void +test_mu_cfind_csv(void) +{ + gchar *cmdline, *output, *erroutput; + + cmdline = g_strdup_printf("%s cfind --muhome=%s --format=csv " + "'testmu\\.xxx?'", + MU_PROGRAM, + CONTACTS_CACHE); if (g_test_verbose()) g_print("%s\n", cmdline); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert (output); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert(output); if (output[1] == 'H') - g_assert_cmpstr (output, - ==, - "\"Helmut Kröger\",\"hk@testmu.xxx\"\n" - "\"Mü\",\"testmu@testmu.xx\"\n"); + g_assert_cmpstr(output, + ==, + "\"Helmut Kröger\",\"hk@testmu.xxx\"\n" + "\"Mü\",\"testmu@testmu.xx\"\n"); else - g_assert_cmpstr (output, - ==, - "\"Mü\",\"testmu@testmu.xx\"\n" - "\"Helmut Kröger\",\"hk@testmu.xxx\"\n"); - g_free (cmdline); - g_free (output); - g_free (erroutput); + g_assert_cmpstr(output, + ==, + "\"Mü\",\"testmu@testmu.xx\"\n" + "\"Helmut Kröger\",\"hk@testmu.xxx\"\n"); + g_free(cmdline); + g_free(output); + g_free(erroutput); } - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); if (!set_en_us_utf8_locale()) return 0; /* don't error out... */ - CONTACTS_CACHE = fill_contacts_cache (); + CONTACTS_CACHE = fill_contacts_cache(); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-plain", test_mu_cfind_plain); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-bbdb", test_mu_cfind_bbdb); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-wl", test_mu_cfind_wl); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-mutt-alias", - test_mu_cfind_mutt_alias); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-mutt-ab", - test_mu_cfind_mutt_ab); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-org-contact", - test_mu_cfind_org_contact); - g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-csv", - test_mu_cfind_csv); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-plain", test_mu_cfind_plain); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-bbdb", test_mu_cfind_bbdb); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-wl", test_mu_cfind_wl); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-mutt-alias", test_mu_cfind_mutt_alias); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-mutt-ab", test_mu_cfind_mutt_ab); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-org-contact", test_mu_cfind_org_contact); + g_test_add_func("/mu-cmd-cfind/test-mu-cfind-csv", test_mu_cfind_csv); - g_log_set_handler (NULL, - (GLogLevelFlags)( - G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| - G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler(NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - rv = g_test_run (); + rv = g_test_run(); - g_free (CONTACTS_CACHE); + g_free(CONTACTS_CACHE); CONTACTS_CACHE = NULL; return rv; diff --git a/mu/test-mu-cmd.cc b/mu/test-mu-cmd.cc index 25e647c3..239ed97d 100644 --- a/mu/test-mu-cmd.cc +++ b/mu/test-mu-cmd.cc @@ -18,7 +18,6 @@ ** */ - #include "config.h" #include @@ -36,38 +35,38 @@ /* tests for the command line interface, uses testdir2 */ -static gchar *DBPATH; /* global */ +static gchar* DBPATH; /* global */ static gchar* -fill_database (void) +fill_database(void) { - gchar *cmdline, *tmpdir; - GError *err; + gchar * cmdline, *tmpdir; + GError* err; - tmpdir = test_mu_common_get_random_tmpdir(); - cmdline = g_strdup_printf ( - "/bin/sh -c '" - "%s init --muhome=%s --maildir=%s --quiet; " - "%s index --muhome=%s --quiet'", - MU_PROGRAM, tmpdir, MU_TESTMAILDIR2, - MU_PROGRAM, tmpdir); + tmpdir = test_mu_common_get_random_tmpdir(); + cmdline = g_strdup_printf("/bin/sh -c '" + "%s init --muhome=%s --maildir=%s --quiet; " + "%s index --muhome=%s --quiet'", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + MU_PROGRAM, + tmpdir); if (g_test_verbose()) - g_print ("%s\n", cmdline); + g_print("%s\n", cmdline); - err = NULL; - if (!g_spawn_command_line_sync (cmdline, NULL, NULL, - NULL, &err)) { - g_printerr ("Error: %s\n", err ? err->message : "?"); - g_assert (0); + err = NULL; + if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &err)) { + g_printerr("Error: %s\n", err ? err->message : "?"); + g_assert(0); } - g_free (cmdline); + g_free(cmdline); return tmpdir; } - static unsigned -newlines_in_output (const char* str) +newlines_in_output(const char* str) { int count; @@ -83,228 +82,207 @@ newlines_in_output (const char* str) } static void -search (const char* query, unsigned expected) +search(const char* query, unsigned expected) { gchar *cmdline, *output, *erroutput; - cmdline = g_strdup_printf ("%s find --muhome=%s %s", - MU_PROGRAM, DBPATH, query); + cmdline = g_strdup_printf("%s find --muhome=%s %s", MU_PROGRAM, DBPATH, query); if (g_test_verbose()) - g_printerr ("\n$ %s\n", cmdline); + g_printerr("\n$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, - &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); if (g_test_verbose()) - g_print ("\nOutput:\n%s", output); - - g_assert_cmpuint (newlines_in_output(output),==,expected); + g_print("\nOutput:\n%s", output); + g_assert_cmpuint(newlines_in_output(output), ==, expected); /* we expect zero lines of error output if there is a match; * otherwise there should be one line 'No matches found' */ /* g_assert_cmpuint (newlines_in_output(erroutput),==, */ /* expected == 0 ? 1 : 0); */ - g_free (output); - g_free (erroutput); - g_free (cmdline); + g_free(output); + g_free(erroutput); + g_free(cmdline); } /* index testdir2, and make sure it adds two documents */ static void -test_mu_index (void) +test_mu_index(void) { - gchar *xpath{g_strdup_printf ("%s%c%s", DBPATH, G_DIR_SEPARATOR, "xapian")}; - g_printerr ("*** %s\n", DBPATH); + gchar* xpath{g_strdup_printf("%s%c%s", DBPATH, G_DIR_SEPARATOR, "xapian")}; + g_printerr("*** %s\n", DBPATH); Mu::Store store{xpath, true}; - g_assert_cmpuint (store.size(), ==, 13); + g_assert_cmpuint(store.size(), ==, 13); - g_free (xpath); + g_free(xpath); } - static void -test_mu_find_empty_query (void) +test_mu_find_empty_query(void) { - search ("\"\"", 13); + search("\"\"", 13); } - static void -test_mu_find_01 (void) +test_mu_find_01(void) { - search ("f:john fruit", 1); - search ("f:soc@example.com", 1); - search ("t:alki@example.com", 1); - search ("t:alcibiades", 1); - search ("http emacs", 1); - search ("f:soc@example.com OR f:john", 2); - search ("f:soc@example.com OR f:john OR t:edmond", 3); - search ("t:julius", 1); - search ("s:dude", 1); - search ("t:dantès", 1); + search("f:john fruit", 1); + search("f:soc@example.com", 1); + search("t:alki@example.com", 1); + search("t:alcibiades", 1); + search("http emacs", 1); + search("f:soc@example.com OR f:john", 2); + search("f:soc@example.com OR f:john OR t:edmond", 3); + search("t:julius", 1); + search("s:dude", 1); + search("t:dantès", 1); } - /* index testdir2, and make sure it adds two documents */ static void -test_mu_find_02 (void) +test_mu_find_02(void) { - search ("bull", 1); - search ("bull m:foo", 0); - search ("bull m:/foo", 1); - search ("bull m:/Foo", 1); - search ("bull flag:a", 1); - search ("g:x", 0); - search ("flag:encrypted", 0); - search ("flag:attach", 1); + search("bull", 1); + search("bull m:foo", 0); + search("bull m:/foo", 1); + search("bull m:/Foo", 1); + search("bull flag:a", 1); + search("g:x", 0); + search("flag:encrypted", 0); + search("flag:attach", 1); } - - static void -test_mu_find_file (void) +test_mu_find_file(void) { - search ("file:sittingbull.jpg", 1); - search ("file:custer.jpg", 1); - search ("file:custer.*", 1); - search ("j:sit*", 1); + search("file:sittingbull.jpg", 1); + search("file:custer.jpg", 1); + search("file:custer.*", 1); + search("j:sit*", 1); } - static void -test_mu_find_mime (void) +test_mu_find_mime(void) { - search ("mime:image/jpeg", 1); - search ("mime:text/plain", 13); - search ("y:text*", 13); - search ("y:image*", 1); - search ("mime:message/rfc822", 2); + search("mime:image/jpeg", 1); + search("mime:text/plain", 13); + search("y:text*", 13); + search("y:image*", 1); + search("mime:message/rfc822", 2); } - static void -test_mu_find_text_in_rfc822 (void) +test_mu_find_text_in_rfc822(void) { - search ("embed:dancing", 1); - search ("e:curious", 1); - search ("embed:with", 2); - search ("e:karjala", 0); - search ("embed:navigation", 1); + search("embed:dancing", 1); + search("e:curious", 1); + search("embed:with", 2); + search("e:karjala", 0); + search("embed:navigation", 1); } - /* some more tests */ static void -test_mu_find_03 (void) +test_mu_find_03(void) { - search ("bull", 1); - search ("bull m:foo", 0); - search ("bull m:/foo", 1); - search ("i:3BE9E6535E0D852173@emss35m06.us.lmco.com", 1); + search("bull", 1); + search("bull m:foo", 0); + search("bull m:/foo", 1); + search("i:3BE9E6535E0D852173@emss35m06.us.lmco.com", 1); } - static void /* error cases */ -test_mu_find_04 (void) +test_mu_find_04(void) { gchar *cmdline, *erroutput; - cmdline = g_strdup_printf ("find %s --muhome=%cfoo%cbar%cnonexistent " - "f:socrates", - MU_PROGRAM, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); + cmdline = g_strdup_printf("find %s --muhome=%cfoo%cbar%cnonexistent " + "f:socrates", + MU_PROGRAM, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); - g_assert (g_spawn_command_line_sync (cmdline, NULL, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, NULL, &erroutput, NULL, NULL)); /* we expect multiple lines of error output */ - g_assert_cmpuint (newlines_in_output(erroutput),>=,1); + g_assert_cmpuint(newlines_in_output(erroutput), >=, 1); - g_free (erroutput); - g_free (cmdline); + g_free(erroutput); + g_free(cmdline); } - G_GNUC_UNUSED static void -test_mu_find_links (void) +test_mu_find_links(void) { gchar *cmdline, *output, *erroutput, *tmpdir; tmpdir = test_mu_common_get_random_tmpdir(); - cmdline = g_strdup_printf ( - "%s find --muhome=%s --format=links --linksdir=%s " - "mime:message/rfc822", MU_PROGRAM, DBPATH, tmpdir); + cmdline = g_strdup_printf("%s find --muhome=%s --format=links --linksdir=%s " + "mime:message/rfc822", + MU_PROGRAM, + DBPATH, + tmpdir); if (g_test_verbose()) - g_print ("cmdline: %s\n", cmdline); + g_print("cmdline: %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, - &output, &erroutput, - NULL, NULL)); - /* there should be no errors */ - g_assert_cmpuint (newlines_in_output(output),==,0); - g_assert_cmpuint (newlines_in_output(erroutput),==,0); - g_free (output); - g_free (erroutput); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + /* there should be no errors */ + g_assert_cmpuint(newlines_in_output(output), ==, 0); + g_assert_cmpuint(newlines_in_output(erroutput), ==, 0); + g_free(output); + g_free(erroutput); /* now we try again, we should get a line of error output, * when we find the first target file already exists */ if (g_test_verbose()) - g_print ("cmdline: %s\n", cmdline); + g_print("cmdline: %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, - &output, &erroutput, - NULL, NULL)); - g_assert_cmpuint (newlines_in_output(output),==,0); - g_assert_cmpuint (newlines_in_output(erroutput),==,1); - g_free (output); - g_free (erroutput); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpuint(newlines_in_output(output), ==, 0); + g_assert_cmpuint(newlines_in_output(erroutput), ==, 1); + g_free(output); + g_free(erroutput); /* now we try again with --clearlinks, and the we should be * back to 0 errors */ - g_free (cmdline); - cmdline = g_strdup_printf ( - "%s find --muhome=%s --format=links --linksdir=%s --clearlinks " - "mime:message/rfc822", MU_PROGRAM, DBPATH, tmpdir); - g_assert (g_spawn_command_line_sync (cmdline, - &output, &erroutput, - NULL, NULL)); + g_free(cmdline); + cmdline = g_strdup_printf("%s find --muhome=%s --format=links --linksdir=%s --clearlinks " + "mime:message/rfc822", + MU_PROGRAM, + DBPATH, + tmpdir); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); if (g_test_verbose()) - g_print ("cmdline: %s\n", cmdline); - g_assert_cmpuint (newlines_in_output(output),==,0); - g_assert_cmpuint (newlines_in_output(erroutput),==,0); - g_free (output); - g_free (erroutput); + g_print("cmdline: %s\n", cmdline); + g_assert_cmpuint(newlines_in_output(output), ==, 0); + g_assert_cmpuint(newlines_in_output(erroutput), ==, 0); + g_free(output); + g_free(erroutput); - g_free (cmdline); - g_free (tmpdir); + g_free(cmdline); + g_free(tmpdir); } - - /* some more tests */ static void -test_mu_find_maildir_special (void) +test_mu_find_maildir_special(void) { - - search ("\"maildir:/wOm_bàT\"", 3); - search ("\"maildir:/wOm*\"", 3); - search ("\"maildir:/wOm_*\"", 3); - search ("\"maildir:wom_bat\"", 0); - search ("\"maildir:/wombat\"", 0); - search ("subject:atoms", 1); - search ("\"maildir:/wom_bat\" subject:atoms", 1); + search("\"maildir:/wOm_bàT\"", 3); + search("\"maildir:/wOm*\"", 3); + search("\"maildir:/wOm_*\"", 3); + search("\"maildir:wom_bat\"", 0); + search("\"maildir:/wombat\"", 0); + search("subject:atoms", 1); + search("\"maildir:/wom_bat\" subject:atoms", 1); } - /* static void */ /* test_mu_find_mime_types (void) */ /* { */ @@ -314,39 +292,37 @@ test_mu_find_maildir_special (void) /* search ("subject:atoms", 1); */ /* } */ - - - static void -test_mu_extract_01 (void) +test_mu_extract_01(void) { gchar *cmdline, *output, *erroutput, *tmpdir; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s extract --muhome=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); + cmdline = g_strdup_printf("%s extract --muhome=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); if (g_test_verbose()) - g_print ("cmd: %s\n", cmdline); + g_print("cmd: %s\n", cmdline); output = erroutput = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); -// ERROR:test-mu-cmd.cc:347:void test_mu_extract_01(): assertion failed (output == "MIME-parts in -// this message:\n" " 1 text/plain [] (27 bytes)\n" " 2 sittingbull.jpg image/jpeg -// [inline] (23.9\302\240kB)\n" " 3 custer.jpg image/jpeg [inline] (21.6\302\240kB)\n"): -// ("MIME-parts in this message:\n 1 text/plain [] (27 bytes)\n 2 sittingbull.jpg -// image/jpeg [inline] (23.9 kB)\n 3 custer.jpg image/jpeg [inline] (21.6 kB)\n" == "MIME-parts in -// this message:\n 1 text/plain [] (27 bytes)\n 2 sittingbull.jpg image/jpeg [inline] -// (23.9\302\240kB)\n 3 custer.jpg image/jpeg [inline] (21.6\302\240kB)\n") + // ERROR:test-mu-cmd.cc:347:void test_mu_extract_01(): assertion failed (output == + // "MIME-parts in this message:\n" " 1 text/plain [] (27 bytes)\n" " 2 + // sittingbull.jpg image/jpeg [inline] (23.9\302\240kB)\n" " 3 custer.jpg image/jpeg + // [inline] (21.6\302\240kB)\n"): + // ("MIME-parts in this message:\n 1 text/plain [] (27 bytes)\n 2 + // sittingbull.jpg image/jpeg [inline] (23.9 kB)\n 3 custer.jpg image/jpeg [inline] (21.6 + // kB)\n" == "MIME-parts in this message:\n 1 text/plain [] (27 bytes)\n 2 + // sittingbull.jpg image/jpeg [inline] (23.9\302\240kB)\n 3 custer.jpg image/jpeg [inline] + // (21.6\302\240kB)\n") /* g_assert_cmpstr (output, */ /* ==, */ /* "MIME-parts in this message:\n" */ @@ -355,21 +331,21 @@ test_mu_extract_01 (void) /* " 3 custer.jpg image/jpeg [inline] (21.6\302\240kB)\n"); */ /* we expect zero lines of error output */ - g_assert_cmpuint (newlines_in_output(erroutput),==,0); + g_assert_cmpuint(newlines_in_output(erroutput), ==, 0); - g_free (output); - g_free (erroutput); - g_free (cmdline); - g_free (tmpdir); + g_free(output); + g_free(erroutput); + g_free(cmdline); + g_free(tmpdir); } static gint64 -get_file_size (const char* path) +get_file_size(const char* path) { - int rv; + int rv; struct stat statbuf; - rv = stat (path, &statbuf); + rv = stat(path, &statbuf); if (rv != 0) { /* g_warning ("error: %s", g_strerror (errno)); */ return -1; @@ -378,218 +354,213 @@ get_file_size (const char* path) return (gint64)statbuf.st_size; } - static void -test_mu_extract_02 (void) +test_mu_extract_02(void) { - gchar *cmdline, *output, *tmpdir; - gchar *att1, *att2; - size_t size; + gchar *cmdline, *output, *tmpdir; + gchar *att1, *att2; + size_t size; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s extract --muhome=%s -a " - "--target-dir=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, - tmpdir, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); + cmdline = g_strdup_printf("%s extract --muhome=%s -a " + "--target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); - att1 = g_strdup_printf ("%s%ccuster.jpg", tmpdir, G_DIR_SEPARATOR); - att2 = g_strdup_printf ("%s%csittingbull.jpg", tmpdir, G_DIR_SEPARATOR); + att1 = g_strdup_printf("%s%ccuster.jpg", tmpdir, G_DIR_SEPARATOR); + att2 = g_strdup_printf("%s%csittingbull.jpg", tmpdir, G_DIR_SEPARATOR); size = get_file_size(att1); - g_assert_true (size >= 15958 && size <= 15960); - g_assert_cmpint (get_file_size(att2),==,17674); + g_assert_true(size >= 15958 && size <= 15960); + g_assert_cmpint(get_file_size(att2), ==, 17674); - g_free (output); - g_free (tmpdir); - g_free (cmdline); - g_free (att1); - g_free (att2); + g_free(output); + g_free(tmpdir); + g_free(cmdline); + g_free(att1); + g_free(att2); } - static void -test_mu_extract_03 (void) +test_mu_extract_03(void) { - gchar *cmdline, *output, *tmpdir; - gchar *att1, *att2; - size_t size; + gchar *cmdline, *output, *tmpdir; + gchar *att1, *att2; + size_t size; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s extract --muhome=%s --parts 3 " - "--target-dir=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, - tmpdir, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - output = NULL; + cmdline = g_strdup_printf("%s extract --muhome=%s --parts 3 " + "--target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + output = NULL; - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); - att1 = g_strdup_printf ("%s%ccuster.jpg", tmpdir, G_DIR_SEPARATOR); - att2 = g_strdup_printf ("%s%csittingbull.jpg", tmpdir, G_DIR_SEPARATOR); + att1 = g_strdup_printf("%s%ccuster.jpg", tmpdir, G_DIR_SEPARATOR); + att2 = g_strdup_printf("%s%csittingbull.jpg", tmpdir, G_DIR_SEPARATOR); size = get_file_size(att1); - g_assert_true (size >= 15958 && size <= 15960); - g_assert_cmpint (get_file_size(att2),==,-1); + g_assert_true(size >= 15958 && size <= 15960); + g_assert_cmpint(get_file_size(att2), ==, -1); - g_free (output); - g_free (tmpdir); - g_free (cmdline); - g_free (att1); - g_free (att2); + g_free(output); + g_free(tmpdir); + g_free(cmdline); + g_free(att1); + g_free(att2); } - static void -test_mu_extract_overwrite (void) +test_mu_extract_overwrite(void) { gchar *cmdline, *output, *erroutput, *tmpdir; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s extract --muhome=%s -a " - "--target-dir=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, tmpdir, tmpdir, - MU_TESTMAILDIR2, G_DIR_SEPARATOR, - G_DIR_SEPARATOR, G_DIR_SEPARATOR); + cmdline = g_strdup_printf("%s extract --muhome=%s -a " + "--target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); - g_assert_cmpstr (erroutput, ==, ""); - g_free (erroutput); - g_free (output); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); + g_assert_cmpstr(erroutput, ==, ""); + g_free(erroutput); + g_free(output); - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); - - return; // XXX fix tests + if (g_test_verbose()) + g_print("$ %s\n", cmdline); /* now, it should fail, because we don't allow overwrites * without --overwrite */ - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); - g_assert_cmpstr (erroutput, !=, ""); - g_free (erroutput); - g_free (output); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); + g_assert_cmpstr(erroutput, !=, ""); + g_free(erroutput); + g_free(output); - g_free (cmdline); + g_free(cmdline); /* this should work now, because we have specified --overwrite */ - cmdline = g_strdup_printf ("%s extract --muhome=%s -a --overwrite " - "--target-dir=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, tmpdir, tmpdir, - MU_TESTMAILDIR2, G_DIR_SEPARATOR, - G_DIR_SEPARATOR, G_DIR_SEPARATOR); - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + cmdline = g_strdup_printf("%s extract --muhome=%s -a --overwrite " + "--target-dir=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); - g_assert_cmpstr (erroutput, ==, ""); - g_free (erroutput); - g_free (output); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); + g_assert_cmpstr(erroutput, ==, ""); + g_free(erroutput); + g_free(output); - g_free (tmpdir); - g_free (cmdline); + g_free(tmpdir); + g_free(cmdline); } - static void -test_mu_extract_by_name (void) +test_mu_extract_by_name(void) { gchar *cmdline, *output, *erroutput, *tmpdir, *path; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s extract --muhome=%s " - "--target-dir=%s %s%cFoo%ccur%cmail5 " - "sittingbull.jpg", - MU_PROGRAM, tmpdir, tmpdir, - MU_TESTMAILDIR2, G_DIR_SEPARATOR, - G_DIR_SEPARATOR, G_DIR_SEPARATOR); + cmdline = g_strdup_printf("%s extract --muhome=%s " + "--target-dir=%s %s%cFoo%ccur%cmail5 " + "sittingbull.jpg", + MU_PROGRAM, + tmpdir, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); - g_assert_cmpstr (erroutput, ==, ""); - path = g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, - "sittingbull.jpg"); - g_assert (access (path, F_OK) == 0); - g_free (path); + g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); + g_assert_cmpstr(erroutput, ==, ""); + path = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "sittingbull.jpg"); + g_assert(access(path, F_OK) == 0); + g_free(path); - g_free (erroutput); - g_free (output); + g_free(erroutput); + g_free(output); - g_free (tmpdir); - g_free (cmdline); + g_free(tmpdir); + g_free(cmdline); } - - - static void -test_mu_view_01 (void) +test_mu_view_01(void) { gchar *cmdline, *output, *tmpdir; - int len; + int len; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s view --muhome=%s %s%cbar%ccur%cmail4", - MU_PROGRAM, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - output = NULL; + cmdline = g_strdup_printf("%s view --muhome=%s %s%cbar%ccur%cmail4", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + output = NULL; - if (g_test_verbose ()) - g_print ("$ %s\n", cmdline); + if (g_test_verbose()) + g_print("$ %s\n", cmdline); - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, !=, NULL); + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, !=, NULL); /* * note: there are two possibilities here; older versions of @@ -613,262 +584,240 @@ test_mu_view_01 (void) */ len = strlen(output); /* g_print ("\n[%s] (%d)\n", output, len); */ - g_assert (len > 349); + g_assert(len > 349); - g_free (output); - g_free (cmdline); - g_free (tmpdir); + g_free(output); + g_free(cmdline); + g_free(tmpdir); } - static void -test_mu_view_multi (void) +test_mu_view_multi(void) { gchar *cmdline, *output, *tmpdir; - int len; + int len; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s view --muhome=%s " - "%s%cbar%ccur%cmail5 " - "%s%cbar%ccur%cmail5", - MU_PROGRAM, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, !=, NULL); + cmdline = g_strdup_printf("%s view --muhome=%s " + "%s%cbar%ccur%cmail5 " + "%s%cbar%ccur%cmail5", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + output = NULL; + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, !=, NULL); len = strlen(output); /* g_print ("\n[%s](%u)\n", output, len); */ - g_assert_cmpuint (len,>,150); + g_assert_cmpuint(len, >, 150); - g_free (output); - g_free (cmdline); - g_free (tmpdir); + g_free(output); + g_free(cmdline); + g_free(tmpdir); } - static void -test_mu_view_multi_separate (void) +test_mu_view_multi_separate(void) { gchar *cmdline, *output, *tmpdir; - int len; + int len; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s view --terminate --muhome=%s " - "%s%cbar%ccur%cmail5 " - "%s%cbar%ccur%cmail5", - MU_PROGRAM, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, !=, NULL); + cmdline = g_strdup_printf("%s view --terminate --muhome=%s " + "%s%cbar%ccur%cmail5 " + "%s%cbar%ccur%cmail5", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + output = NULL; + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, !=, NULL); len = strlen(output); /* g_print ("\n[%s](%u)\n", output, len); */ - g_assert_cmpuint (len,>,150); + g_assert_cmpuint(len, >, 150); - g_free (output); - g_free (cmdline); - g_free (tmpdir); + g_free(output); + g_free(cmdline); + g_free(tmpdir); } - - - static void -test_mu_view_attach (void) +test_mu_view_attach(void) { gchar *cmdline, *output, *tmpdir; - int len; + int len; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s view --muhome=%s %s%cFoo%ccur%cmail5", - MU_PROGRAM, - tmpdir, - MU_TESTMAILDIR2, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, !=, NULL); + cmdline = g_strdup_printf("%s view --muhome=%s %s%cFoo%ccur%cmail5", + MU_PROGRAM, + tmpdir, + MU_TESTMAILDIR2, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR, + G_DIR_SEPARATOR); + output = NULL; + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, !=, NULL); len = strlen(output); - g_assert (len == 168 || len == 166); + g_assert(len == 168 || len == 166); - g_free (output); - g_free (cmdline); - g_free (tmpdir); + g_free(output); + g_free(cmdline); + g_free(tmpdir); } - - static void -test_mu_mkdir_01 (void) +test_mu_mkdir_01(void) { - gchar *cmdline, *output, *tmpdir; - gchar *dir; + gchar *cmdline, *output, *tmpdir; + gchar* dir; tmpdir = test_mu_common_get_random_tmpdir(); - g_assert (g_mkdir_with_parents (tmpdir, 0700) == 0); + g_assert(g_mkdir_with_parents(tmpdir, 0700) == 0); - cmdline = g_strdup_printf ("%s mkdir --muhome=%s %s%ctest1 %s%ctest2", - MU_PROGRAM,tmpdir, - tmpdir, G_DIR_SEPARATOR, - tmpdir, G_DIR_SEPARATOR); + cmdline = g_strdup_printf("%s mkdir --muhome=%s %s%ctest1 %s%ctest2", + MU_PROGRAM, + tmpdir, + tmpdir, + G_DIR_SEPARATOR, + tmpdir, + G_DIR_SEPARATOR); output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - NULL, NULL)); - g_assert_cmpstr (output, ==, ""); + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, NULL, NULL)); + g_assert_cmpstr(output, ==, ""); - dir = g_strdup_printf ("%s%ctest1%ccur", tmpdir, G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - g_assert (access (dir, F_OK) == 0); - g_free (dir); + dir = g_strdup_printf("%s%ctest1%ccur", tmpdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR); + g_assert(access(dir, F_OK) == 0); + g_free(dir); - dir = g_strdup_printf ("%s%ctest2%ctmp", tmpdir, G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - g_assert (access (dir, F_OK) == 0); - g_free (dir); + dir = g_strdup_printf("%s%ctest2%ctmp", tmpdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR); + g_assert(access(dir, F_OK) == 0); + g_free(dir); - dir = g_strdup_printf ("%s%ctest1%cnew", tmpdir, G_DIR_SEPARATOR, - G_DIR_SEPARATOR); - g_assert (access (dir, F_OK) == 0); - g_free (dir); + dir = g_strdup_printf("%s%ctest1%cnew", tmpdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR); + g_assert(access(dir, F_OK) == 0); + g_free(dir); - g_free (output); - g_free (tmpdir); - g_free (cmdline); + g_free(output); + g_free(tmpdir); + g_free(cmdline); } /* we can only test 'verify' if gpg is installed, and has * djcb@djcbsoftware's key in the keyring */ G_GNUC_UNUSED static gboolean -verify_is_testable (void) +verify_is_testable(void) { - gchar *gpg, *cmdline; - gchar *output, *erroutput; - int retval; + gchar * gpg, *cmdline; + gchar * output, *erroutput; + int retval; gboolean rv; /* find GPG or return FALSE */ - if ((gpg = (char*)g_getenv ("MU_GPG_PATH"))) { - if (access (gpg, X_OK) != 0) + if ((gpg = (char*)g_getenv("MU_GPG_PATH"))) { + if (access(gpg, X_OK) != 0) return FALSE; else - gpg = g_strdup (gpg); + gpg = g_strdup(gpg); - } else if (!(gpg = g_find_program_in_path ("gpg2"))) + } else if (!(gpg = g_find_program_in_path("gpg2"))) return FALSE; - cmdline = g_strdup_printf ("%s --list-keys DCC4A036", gpg); - g_free (gpg); + cmdline = g_strdup_printf("%s --list-keys DCC4A036", gpg); + g_free(gpg); output = erroutput = NULL; - rv = g_spawn_command_line_sync (cmdline, &output, &erroutput, - &retval, NULL); - g_free (output); - g_free (erroutput); - g_free (cmdline); + rv = g_spawn_command_line_sync(cmdline, &output, &erroutput, &retval, NULL); + g_free(output); + g_free(erroutput); + g_free(cmdline); - return (rv && retval == 0) ? TRUE:FALSE; + return (rv && retval == 0) ? TRUE : FALSE; } G_GNUC_UNUSED static void -test_mu_verify_good (void) +test_mu_verify_good(void) { gchar *cmdline, *output; - int retval; + int retval; - if (!verify_is_testable ()) + if (!verify_is_testable()) return; - cmdline = g_strdup_printf ("%s verify %s/signed!2,S", - MU_PROGRAM, MU_TESTMAILDIR4); + cmdline = g_strdup_printf("%s verify %s/signed!2,S", MU_PROGRAM, MU_TESTMAILDIR4); if (g_test_verbose()) - g_print ("$ %s\n", cmdline); + g_print("$ %s\n", cmdline); output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - &retval, NULL)); - g_free (output); - g_assert_cmpuint (retval, ==, 0); - g_free (cmdline); - + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, &retval, NULL)); + g_free(output); + g_assert_cmpuint(retval, ==, 0); + g_free(cmdline); } - -G_GNUC_UNUSED static void -test_mu_verify_bad (void) +G_GNUC_UNUSED static void +test_mu_verify_bad(void) { gchar *cmdline, *output; - int retval; + int retval; - if (!verify_is_testable ()) + if (!verify_is_testable()) return; - cmdline = g_strdup_printf ("%s verify %s/signed-bad!2,S", - MU_PROGRAM, - MU_TESTMAILDIR4); + cmdline = g_strdup_printf("%s verify %s/signed-bad!2,S", MU_PROGRAM, MU_TESTMAILDIR4); if (g_test_verbose()) - g_print ("$ %s\n", cmdline); + g_print("$ %s\n", cmdline); output = NULL; - g_assert (g_spawn_command_line_sync (cmdline, &output, NULL, - &retval, NULL)); - g_free (output); - g_assert_cmpuint (retval, !=, 0); - g_free (cmdline); + g_assert(g_spawn_command_line_sync(cmdline, &output, NULL, &retval, NULL)); + g_free(output); + g_assert_cmpuint(retval, !=, 0); + g_free(cmdline); } - - int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); if (!set_en_us_utf8_locale()) return 0; /* don't error out... */ - g_test_add_func ("/mu-cmd/test-mu-index", test_mu_index); + g_test_add_func("/mu-cmd/test-mu-index", test_mu_index); - g_test_add_func ("/mu-cmd/test-mu-find-empty-query", - test_mu_find_empty_query); - g_test_add_func ("/mu-cmd/test-mu-find-01", test_mu_find_01); - g_test_add_func ("/mu-cmd/test-mu-find-02", test_mu_find_02); + g_test_add_func("/mu-cmd/test-mu-find-empty-query", test_mu_find_empty_query); + g_test_add_func("/mu-cmd/test-mu-find-01", test_mu_find_01); + g_test_add_func("/mu-cmd/test-mu-find-02", test_mu_find_02); - g_test_add_func ("/mu-cmd/test-mu-find-file", test_mu_find_file); - g_test_add_func ("/mu-cmd/test-mu-find-mime", test_mu_find_mime); + g_test_add_func("/mu-cmd/test-mu-find-file", test_mu_find_file); + g_test_add_func("/mu-cmd/test-mu-find-mime", test_mu_find_mime); /* recently, this test breaks _sometimes_ when run on Travis; but it * seems related to the setup there, as nothing has changed in the code. @@ -876,41 +825,35 @@ main (int argc, char *argv[]) /* g_test_add_func ("/mu-cmd/test-mu-find-links", * test_mu_find_links); */ - g_test_add_func ("/mu-cmd/test-mu-find-text-in-rfc822", - test_mu_find_text_in_rfc822); + g_test_add_func("/mu-cmd/test-mu-find-text-in-rfc822", test_mu_find_text_in_rfc822); - g_test_add_func ("/mu-cmd/test-mu-find-03", test_mu_find_03); - g_test_add_func ("/mu-cmd/test-mu-find-04", test_mu_find_04); - g_test_add_func ("/mu-cmd/test-mu-find-maildir-special", - test_mu_find_maildir_special); - g_test_add_func ("/mu-cmd/test-mu-extract-01", test_mu_extract_01); - g_test_add_func ("/mu-cmd/test-mu-extract-02", test_mu_extract_02); - g_test_add_func ("/mu-cmd/test-mu-extract-03", test_mu_extract_03); - g_test_add_func ("/mu-cmd/test-mu-extract-overwrite", - test_mu_extract_overwrite); - g_test_add_func ("/mu-cmd/test-mu-extract-by-name", - test_mu_extract_by_name); + g_test_add_func("/mu-cmd/test-mu-find-03", test_mu_find_03); + g_test_add_func("/mu-cmd/test-mu-find-04", test_mu_find_04); + g_test_add_func("/mu-cmd/test-mu-find-maildir-special", test_mu_find_maildir_special); + g_test_add_func("/mu-cmd/test-mu-extract-01", test_mu_extract_01); + g_test_add_func("/mu-cmd/test-mu-extract-02", test_mu_extract_02); + g_test_add_func("/mu-cmd/test-mu-extract-03", test_mu_extract_03); + g_test_add_func("/mu-cmd/test-mu-extract-overwrite", test_mu_extract_overwrite); + g_test_add_func("/mu-cmd/test-mu-extract-by-name", test_mu_extract_by_name); - g_test_add_func ("/mu-cmd/test-mu-view-01", test_mu_view_01); - g_test_add_func ("/mu-cmd/test-mu-view-multi", - test_mu_view_multi); - g_test_add_func ("/mu-cmd/test-mu-view-multi-separate", - test_mu_view_multi_separate); - g_test_add_func ("/mu-cmd/test-mu-view-attach", test_mu_view_attach); - g_test_add_func ("/mu-cmd/test-mu-mkdir-01", test_mu_mkdir_01); + g_test_add_func("/mu-cmd/test-mu-view-01", test_mu_view_01); + g_test_add_func("/mu-cmd/test-mu-view-multi", test_mu_view_multi); + g_test_add_func("/mu-cmd/test-mu-view-multi-separate", test_mu_view_multi_separate); + g_test_add_func("/mu-cmd/test-mu-view-attach", test_mu_view_attach); + g_test_add_func("/mu-cmd/test-mu-mkdir-01", test_mu_mkdir_01); - g_test_add_func ("/mu-cmd/test-mu-verify-good", test_mu_verify_good); - g_test_add_func ("/mu-cmd/test-mu-verify-bad", test_mu_verify_bad); + g_test_add_func("/mu-cmd/test-mu-verify-good", test_mu_verify_good); + g_test_add_func("/mu-cmd/test-mu-verify-bad", test_mu_verify_bad); - g_log_set_handler (NULL, - (GLogLevelFlags)( - G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| - G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); + g_log_set_handler(NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING | + G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); - DBPATH = fill_database (); - rv = g_test_run (); - g_free (DBPATH); + DBPATH = fill_database(); + rv = g_test_run(); + g_free(DBPATH); return rv; } diff --git a/mu/test-mu-query.cc b/mu/test-mu-query.cc index 14337d8c..2587eb57 100644 --- a/mu/test-mu-query.cc +++ b/mu/test-mu-query.cc @@ -42,24 +42,24 @@ static std::string DB_PATH1; static std::string DB_PATH2; static std::string -make_database (const std::string& testdir) +make_database(const std::string& testdir) { - char *tmpdir{test_mu_common_get_random_tmpdir()}; - const auto cmdline{ - format("/bin/sh -c '" - "%s init --muhome=%s --maildir=%s --quiet ; " - "%s index --muhome=%s --quiet'", - MU_PROGRAM, tmpdir, testdir.c_str(), - MU_PROGRAM, tmpdir)}; - + char* tmpdir{test_mu_common_get_random_tmpdir()}; + const auto cmdline{format("/bin/sh -c '" + "%s init --muhome=%s --maildir=%s --quiet ; " + "%s index --muhome=%s --quiet'", + MU_PROGRAM, + tmpdir, + testdir.c_str(), + MU_PROGRAM, + tmpdir)}; if (g_test_verbose()) - g_printerr ("\n%s\n", cmdline.c_str()); + g_printerr("\n%s\n", cmdline.c_str()); - g_assert (g_spawn_command_line_sync (cmdline.c_str(), NULL, NULL, - NULL, NULL)); - auto xpath= g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, "xapian"); - g_free (tmpdir); + g_assert(g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, NULL, NULL)); + auto xpath = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "xapian"); + g_free(tmpdir); std::string dbpath{xpath}; g_free(xpath); @@ -67,518 +67,476 @@ make_database (const std::string& testdir) return dbpath; } - - static void -assert_no_dups (const QueryResults& qres) +assert_no_dups(const QueryResults& qres) { - std::unordered_set msgid_set, path_set; + std::unordered_set msgid_set, path_set; - for (auto&& mi: qres) { - g_assert_true(msgid_set.find(mi.message_id().value()) == msgid_set.end()); - g_assert_true(path_set.find(mi.path().value()) == path_set.end()); + for (auto&& mi : qres) { + g_assert_true(msgid_set.find(mi.message_id().value()) == msgid_set.end()); + g_assert_true(path_set.find(mi.path().value()) == path_set.end()); - path_set.emplace(*mi.path()); - msgid_set.emplace(*mi.message_id()); + path_set.emplace(*mi.path()); + msgid_set.emplace(*mi.message_id()); - g_assert_false(msgid_set.find(mi.message_id().value()) == msgid_set.end()); - g_assert_false(path_set.find(mi.path().value()) == path_set.end()); - } + g_assert_false(msgid_set.find(mi.message_id().value()) == msgid_set.end()); + g_assert_false(path_set.find(mi.path().value()) == path_set.end()); + } } - /* note: this also *moves the iter* */ static size_t -run_and_count_matches (const std::string& xpath, const std::string& expr, - Mu::QueryFlags flags = Mu::QueryFlags::None) +run_and_count_matches(const std::string& xpath, + const std::string& expr, + Mu::QueryFlags flags = Mu::QueryFlags::None) { Mu::Store store{xpath}; Mu::Query query{store}; if (g_test_verbose()) { - std::cout << "==> mquery: " << query.parse (expr, false) << "\n"; - std::cout << "==> xquery: " << query.parse (expr, true) << "\n"; + std::cout << "==> mquery: " << query.parse(expr, false) << "\n"; + std::cout << "==> xquery: " << query.parse(expr, true) << "\n"; } Mu::allow_warnings(); - auto qres{query.run (expr, MU_MSG_FIELD_ID_NONE, flags)}; - g_assert_true (!!qres); - assert_no_dups (*qres); + auto qres{query.run(expr, MU_MSG_FIELD_ID_NONE, flags)}; + g_assert_true(!!qres); + assert_no_dups(*qres); return qres->size(); } -typedef struct { - const char *query; - size_t count; /* expected number of matches */ +typedef struct { + const char* query; + size_t count; /* expected number of matches */ } QResults; static void -test_mu_query_01 (void) +test_mu_query_01(void) { - int i; + int i; QResults queries[] = { - { "basic", 3 }, - { "question", 5 }, - { "thanks", 2 }, - { "html", 4 }, - { "subject:exception", 1 }, - { "exception", 1 }, - { "subject:A&B", 1 }, - { "A&B", 1 }, - { "subject:elisp", 1 }, - { "html AND contains", 1 }, - { "html and contains", 1 }, - { "from:pepernoot", 0 }, - { "foo:pepernoot", 0 }, - { "funky", 1 }, - { "fünkÿ", 1 }, - // { "", 18 }, - { "msgid:abcd$efgh@example.com", 1}, - { "i:abcd$efgh@example.com", 1}, + {"basic", 3}, + {"question", 5}, + {"thanks", 2}, + {"html", 4}, + {"subject:exception", 1}, + {"exception", 1}, + {"subject:A&B", 1}, + {"A&B", 1}, + {"subject:elisp", 1}, + {"html AND contains", 1}, + {"html and contains", 1}, + {"from:pepernoot", 0}, + {"foo:pepernoot", 0}, + {"funky", 1}, + {"fünkÿ", 1}, + // { "", 18 }, + {"msgid:abcd$efgh@example.com", 1}, + {"i:abcd$efgh@example.com", 1}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } static void -test_mu_query_02 (void) +test_mu_query_02(void) { const char* q; q = "i:f7ccd24b0808061357t453f5962w8b61f9a453b684d0@mail.gmail.com"; - g_assert_cmpuint (run_and_count_matches (DB_PATH1, q), ==, 1); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, q), ==, 1); } - static void -test_mu_query_03 (void) +test_mu_query_03(void) { - int i; - QResults queries[] = { - { "ploughed", 1}, - { "i:3BE9E6535E3029448670913581E7A1A20D852173@" - "emss35m06.us.lmco.com", 1}, - { "i:!&!AAAAAAAAAYAAAAAAAAAOH1+8mkk+lLn7Gg5fke7" - "FbCgAAAEAAAAJ7eBDgcactKhXL6r8cEnJ8BAAAAAA==@" - "example.com", 1}, + int i; + QResults queries[] = {{"ploughed", 1}, + {"i:3BE9E6535E3029448670913581E7A1A20D852173@" + "emss35m06.us.lmco.com", + 1}, + {"i:!&!AAAAAAAAAYAAAAAAAAAOH1+8mkk+lLn7Gg5fke7" + "FbCgAAAEAAAAJ7eBDgcactKhXL6r8cEnJ8BAAAAAA==@" + "example.com", + 1}, - /* subsets of the words in the subject should match */ - { "s:gcc include search order" , 1}, - { "s:gcc include search" , 1}, - { "s:search order" , 1}, - { "s:include" , 1}, + /* subsets of the words in the subject should match */ + {"s:gcc include search order", 1}, + {"s:gcc include search", 1}, + {"s:search order", 1}, + {"s:include", 1}, - { "s:lisp", 1}, - { "s:LISP", 1}, + {"s:lisp", 1}, + {"s:LISP", 1}, - /* { "s:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */ - /* { "subject:Re: Learning LISP; Scheme vs elisp.", 1}, */ - /* { "subject:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */ - { "to:help-gnu-emacs@gnu.org", 4}, - { "t:help-gnu-emacs", 4}, - { "flag:flagged", 1} - }; + /* { "s:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */ + /* { "subject:Re: Learning LISP; Scheme vs elisp.", 1}, */ + /* { "subject:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */ + {"to:help-gnu-emacs@gnu.org", 4}, + {"t:help-gnu-emacs", 4}, + {"flag:flagged", 1}}; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } - static void -test_mu_query_04 (void) +test_mu_query_04(void) { int i; QResults queries[] = { - { "frodo@example.com", 1}, - { "f:frodo@example.com", 1}, - { "f:Frodo Baggins", 1}, - { "bilbo@anotherexample.com", 1}, - { "t:bilbo@anotherexample.com", 1}, - { "t:bilbo", 1}, - { "f:bilbo", 0}, - { "baggins", 1}, - { "prio:h", 1}, - { "prio:high", 1}, - { "prio:normal", 11}, - { "prio:l", 7}, - { "not prio:l", 12}, + {"frodo@example.com", 1}, + {"f:frodo@example.com", 1}, + {"f:Frodo Baggins", 1}, + {"bilbo@anotherexample.com", 1}, + {"t:bilbo@anotherexample.com", 1}, + {"t:bilbo", 1}, + {"f:bilbo", 0}, + {"baggins", 1}, + {"prio:h", 1}, + {"prio:high", 1}, + {"prio:normal", 11}, + {"prio:l", 7}, + {"not prio:l", 12}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } - static void -test_mu_query_logic (void) +test_mu_query_logic(void) { - int i; - QResults queries[] = { - { "subject:gcc" , 1}, - { "subject:lisp" , 1}, - { "subject:gcc OR subject:lisp" , 2}, - { "subject:gcc or subject:lisp" , 2}, - { "subject:gcc AND subject:lisp" , 0}, + int i; + QResults queries[] = {{"subject:gcc", 1}, + {"subject:lisp", 1}, + {"subject:gcc OR subject:lisp", 2}, + {"subject:gcc or subject:lisp", 2}, + {"subject:gcc AND subject:lisp", 0}, - { "subject:gcc OR (subject:scheme AND subject:elisp)" , 2}, - { "(subject:gcc OR subject:scheme) AND subject:elisp" , 1} - }; + {"subject:gcc OR (subject:scheme AND subject:elisp)", 2}, + {"(subject:gcc OR subject:scheme) AND subject:elisp", 1}}; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } static void -test_mu_query_accented_chars_01 (void) +test_mu_query_accented_chars_01(void) { Store store{DB_PATH1}; Query q{store}; - auto qres{q.run("fünkÿ")}; - g_assert_true(!!qres); - g_assert_false(qres->empty()); + auto qres{q.run("fünkÿ")}; + g_assert_true(!!qres); + g_assert_false(qres->empty()); - auto begin{qres->begin()}; - auto msg{begin.floating_msg()}; + auto begin{qres->begin()}; + auto msg{begin.floating_msg()}; if (!msg) { - g_warning ("error getting message"); - g_assert_not_reached (); + g_warning("error getting message"); + g_assert_not_reached(); } - g_assert_cmpstr (mu_msg_get_subject(msg),==, - "Greetings from Lothlórien"); + g_assert_cmpstr(mu_msg_get_subject(msg), ==, "Greetings from Lothlórien"); /* TODO: fix this again */ - auto summ = mu_str_summarize (mu_msg_get_body_text - (msg, MU_MSG_OPTION_NONE), 5); - g_assert_cmpstr (summ,==, - "Let's write some fünkÿ text using umlauts. Foo."); - g_free (summ); + auto summ = mu_str_summarize(mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), 5); + g_assert_cmpstr(summ, ==, "Let's write some fünkÿ text using umlauts. Foo."); + g_free(summ); } static void -test_mu_query_accented_chars_02 (void) +test_mu_query_accented_chars_02(void) { int i; - QResults queries[] = { - { "f:mü", 1}, - { "s:motörhead", 1}, - { "t:Helmut", 1}, - { "t:Kröger", 1}, - { "s:MotorHeäD", 1}, - { "queensryche", 1}, - { "Queensrÿche", 1} - }; + QResults queries[] = {{"f:mü", 1}, + {"s:motörhead", 1}, + {"t:Helmut", 1}, + {"t:Kröger", 1}, + {"s:MotorHeäD", 1}, + {"queensryche", 1}, + {"Queensrÿche", 1}}; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } - static void -test_mu_query_accented_chars_fraiche (void) +test_mu_query_accented_chars_fraiche(void) { int i; - QResults queries[] = { - { "crème fraîche", 1}, - { "creme fraiche", 1}, - { "fraîche crème", 1}, - { "будланула", 1}, - { "БУДЛАНУЛА", 1}, - { "CRÈME FRAÎCHE", 1}, - { "CREME FRAICHE", 1} - }; + QResults queries[] = {{"crème fraîche", 1}, + {"creme fraiche", 1}, + {"fraîche crème", 1}, + {"будланула", 1}, + {"БУДЛАНУЛА", 1}, + {"CRÈME FRAÎCHE", 1}, + {"CREME FRAICHE", 1}}; for (i = 0; i != G_N_ELEMENTS(queries); ++i) { + if (g_test_verbose()) + g_print("'%s'\n", queries[i].query); - if (g_test_verbose ()) - g_print ("'%s'\n", queries[i].query); - - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } } static void -test_mu_query_wildcards (void) +test_mu_query_wildcards(void) { int i; QResults queries[] = { - { "f:mü", 1}, - { "s:mo*", 1}, - { "t:Helm*", 1}, - { "queensryche", 1}, - { "Queen*", 1}, + {"f:mü", 1}, + {"s:mo*", 1}, + {"t:Helm*", 1}, + {"queensryche", 1}, + {"Queen*", 1}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); -} - - -static void -test_mu_query_dates_helsinki (void) -{ - int i; - const char *old_tz; - - QResults queries[] = { - { "date:20080731..20080804", 5}, - { "date:20080731..20080804 s:gcc", 1}, - { "date:200808110803..now", 7}, - { "date:200808110803..today",7}, - { "date:200808110801..now", 7} - }; - - old_tz = set_tz ("Europe/Helsinki"); - - const auto xpath{make_database (MU_TESTMAILDIR)}; - g_assert_false (xpath.empty()); - - for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches - (xpath, queries[i].query), - ==, queries[i].count); - - set_tz (old_tz); - + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } static void -test_mu_query_dates_sydney (void) +test_mu_query_dates_helsinki(void) { - int i; - const char *old_tz; - QResults queries[] = { - { "date:20080731..20080804", 5}, - { "date:20080731..20080804 s:gcc", 1}, - { "date:200808110803..now", 7}, - { "date:200808110803..today", 7}, - { "date:200808110801..now", 7} - }; + int i; + const char* old_tz; - old_tz = set_tz ("Australia/Sydney"); + QResults queries[] = {{"date:20080731..20080804", 5}, + {"date:20080731..20080804 s:gcc", 1}, + {"date:200808110803..now", 7}, + {"date:200808110803..today", 7}, + {"date:200808110801..now", 7}}; + + old_tz = set_tz("Europe/Helsinki"); const auto xpath{make_database(MU_TESTMAILDIR)}; - g_assert_false (xpath.empty()); + g_assert_false(xpath.empty()); for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches - (xpath, queries[i].query), - ==, queries[i].count); - set_tz (old_tz); + g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query), + ==, + queries[i].count); + + set_tz(old_tz); } static void -test_mu_query_dates_la (void) +test_mu_query_dates_sydney(void) { - int i; - const char *old_tz; + int i; + const char* old_tz; + QResults queries[] = {{"date:20080731..20080804", 5}, + {"date:20080731..20080804 s:gcc", 1}, + {"date:200808110803..now", 7}, + {"date:200808110803..today", 7}, + {"date:200808110801..now", 7}}; - QResults queries[] = { - { "date:20080731..20080804", 5}, - { "date:2008-07-31..2008-08-04", 5}, - { "date:20080804..20080731", 5}, - { "date:20080731..20080804 s:gcc", 1}, - { "date:200808110803..now", 6}, - { "date:200808110803..today", 6}, - { "date:200808110801..now", 6} - }; + old_tz = set_tz("Australia/Sydney"); - old_tz = set_tz ("America/Los_Angeles"); + const auto xpath{make_database(MU_TESTMAILDIR)}; + g_assert_false(xpath.empty()); - const auto xpath = make_database (MU_TESTMAILDIR); - g_assert_false (xpath.empty()); + for (i = 0; i != G_N_ELEMENTS(queries); ++i) + g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query), + ==, + queries[i].count); + set_tz(old_tz); +} + +static void +test_mu_query_dates_la(void) +{ + int i; + const char* old_tz; + + QResults queries[] = {{"date:20080731..20080804", 5}, + {"date:2008-07-31..2008-08-04", 5}, + {"date:20080804..20080731", 5}, + {"date:20080731..20080804 s:gcc", 1}, + {"date:200808110803..now", 6}, + {"date:200808110803..today", 6}, + {"date:200808110801..now", 6}}; + + old_tz = set_tz("America/Los_Angeles"); + + const auto xpath = make_database(MU_TESTMAILDIR); + g_assert_false(xpath.empty()); for (i = 0; i != G_N_ELEMENTS(queries); ++i) { /* g_print ("%s\n", queries[i].query); */ - g_assert_cmpuint (run_and_count_matches - (xpath, queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query), + ==, + queries[i].count); } - set_tz (old_tz); + set_tz(old_tz); } - - - static void -test_mu_query_sizes (void) +test_mu_query_sizes(void) { - int i; + int i; QResults queries[] = { - { "size:0b..2m", 19}, - { "size:3b..2m", 19}, - { "size:2k..4k", 4}, + {"size:0b..2m", 19}, + {"size:3b..2m", 19}, + {"size:2k..4k", 4}, - { "size:0b..2m", 19}, - { "size:2m..0b", 19}, + {"size:0b..2m", 19}, + {"size:2m..0b", 19}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); - + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } - static void -test_mu_query_attach (void) +test_mu_query_attach(void) { - int i; - QResults queries[] = { - { "j:sittingbull.jpg", 1}, - { "file:custer", 0}, - { "file:custer.jpg", 1} - }; + int i; + QResults queries[] = {{"j:sittingbull.jpg", 1}, {"file:custer", 0}, {"file:custer.jpg", 1}}; for (i = 0; i != G_N_ELEMENTS(queries); ++i) { if (g_test_verbose()) - g_print ("query: %s\n", queries[i].query); - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_print("query: %s\n", queries[i].query); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } } - - - - static void -test_mu_query_msgid (void) +test_mu_query_msgid(void) { - int i; + int i; QResults queries[] = { - { "i:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz" - "=bfogtmbGGs5A@mail.gmail.com", 1}, - { "msgid:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz=" - "bfogtmbGGs5A@mail.gmail.com", 1}, + {"i:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz" + "=bfogtmbGGs5A@mail.gmail.com", + 1}, + {"msgid:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz=" + "bfogtmbGGs5A@mail.gmail.com", + 1}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) { if (g_test_verbose()) - g_print ("query: %s\n", queries[i].query); - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_print("query: %s\n", queries[i].query); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } } - static void -test_mu_query_tags (void) +test_mu_query_tags(void) { - int i; + int i; QResults queries[] = { - { "x:paradise", 1}, - { "tag:lost", 1}, - { "tag:lost tag:paradise", 1}, - { "tag:lost tag:horizon", 0}, - { "tag:lost OR tag:horizon", 1}, - { "x:paradise,lost", 0}, - { "x:paradise AND x:lost", 1}, - { "x:\\\\backslash", 1}, + {"x:paradise", 1}, + {"tag:lost", 1}, + {"tag:lost tag:paradise", 1}, + {"tag:lost tag:horizon", 0}, + {"tag:lost OR tag:horizon", 1}, + {"x:paradise,lost", 0}, + {"x:paradise AND x:lost", 1}, + {"x:\\\\backslash", 1}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } - - - static void -test_mu_query_wom_bat (void) +test_mu_query_wom_bat(void) { - int i; + int i; QResults queries[] = { - { "maildir:/wom_bat", 3}, - //{ "\"maildir:/wom bat\"", 3}, - // as expected, no longer works with new parser + {"maildir:/wom_bat", 3}, + //{ "\"maildir:/wom bat\"", 3}, + // as expected, no longer works with new parser }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } - - static void -test_mu_query_signed_encrypted (void) +test_mu_query_signed_encrypted(void) { - int i; + int i; QResults queries[] = { - { "flag:encrypted", 2}, - { "flag:signed", 2}, + {"flag:encrypted", 2}, + {"flag:signed", 2}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } - static void -test_mu_query_multi_to_cc (void) +test_mu_query_multi_to_cc(void) { - int i; + int i; QResults queries[] = { - { "to:a@example.com", 1}, - { "cc:d@example.com", 1}, - { "to:b@example.com", 1}, - { "cc:e@example.com", 1}, - { "cc:e@example.com AND cc:d@example.com", 1}, + {"to:a@example.com", 1}, + {"cc:d@example.com", 1}, + {"to:b@example.com", 1}, + {"cc:e@example.com", 1}, + {"cc:e@example.com AND cc:d@example.com", 1}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) - g_assert_cmpuint (run_and_count_matches (DB_PATH1, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query), + ==, + queries[i].count); } static void -test_mu_query_tags_02 (void) +test_mu_query_tags_02(void) { - int i; + int i; QResults queries[] = { - { "x:paradise", 1}, - { "tag:@NextActions", 1}, - { "x:queensrÿche", 1}, - { "tag:lost OR tag:operation*", 2}, + {"x:paradise", 1}, + {"tag:@NextActions", 1}, + {"x:queensrÿche", 1}, + {"tag:lost OR tag:operation*", 2}, }; for (i = 0; i != G_N_ELEMENTS(queries); ++i) { - g_assert_cmpuint (run_and_count_matches (DB_PATH2, - queries[i].query), - ==, queries[i].count); + g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query), + ==, + queries[i].count); } } @@ -588,87 +546,75 @@ test_mu_query_tags_02 (void) --related option doesn't work. */ static void -test_mu_query_threads_compilation_error (void) +test_mu_query_threads_compilation_error(void) { - const auto xpath = make_database (MU_TESTMAILDIR); + const auto xpath = make_database(MU_TESTMAILDIR); - g_assert_cmpuint (run_and_count_matches - (xpath, "msgid:uwsireh25.fsf@one.dot.net"), - ==, 1); + g_assert_cmpuint(run_and_count_matches(xpath, "msgid:uwsireh25.fsf@one.dot.net"), ==, 1); - g_assert_cmpuint (run_and_count_matches - (xpath, "msgid:uwsireh25.fsf@one.dot.net", - QueryFlags::IncludeRelated), - ==, 3); + g_assert_cmpuint(run_and_count_matches(xpath, + "msgid:uwsireh25.fsf@one.dot.net", + QueryFlags::IncludeRelated), + ==, + 3); } int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { int rv; - setlocale (LC_ALL, ""); + setlocale(LC_ALL, ""); - g_test_init (&argc, &argv, NULL); + g_test_init(&argc, &argv, NULL); - DB_PATH1 = make_database (MU_TESTMAILDIR); - g_assert_false (DB_PATH1.empty()); + DB_PATH1 = make_database(MU_TESTMAILDIR); + g_assert_false(DB_PATH1.empty()); - DB_PATH2 = make_database (MU_TESTMAILDIR2); - g_assert_false (DB_PATH2.empty()); + DB_PATH2 = make_database(MU_TESTMAILDIR2); + g_assert_false(DB_PATH2.empty()); - g_test_add_func ("/mu-query/test-mu-query-01", test_mu_query_01); - g_test_add_func ("/mu-query/test-mu-query-02", test_mu_query_02); - g_test_add_func ("/mu-query/test-mu-query-03", test_mu_query_03); - g_test_add_func ("/mu-query/test-mu-query-04", test_mu_query_04); + g_test_add_func("/mu-query/test-mu-query-01", test_mu_query_01); + g_test_add_func("/mu-query/test-mu-query-02", test_mu_query_02); + g_test_add_func("/mu-query/test-mu-query-03", test_mu_query_03); + g_test_add_func("/mu-query/test-mu-query-04", test_mu_query_04); - g_test_add_func ("/mu-query/test-mu-query-signed-encrypted", - test_mu_query_signed_encrypted); - g_test_add_func ("/mu-query/test-mu-query-multi-to-cc", - test_mu_query_multi_to_cc); - g_test_add_func ("/mu-query/test-mu-query-logic", test_mu_query_logic); + g_test_add_func("/mu-query/test-mu-query-signed-encrypted", test_mu_query_signed_encrypted); + g_test_add_func("/mu-query/test-mu-query-multi-to-cc", test_mu_query_multi_to_cc); + g_test_add_func("/mu-query/test-mu-query-logic", test_mu_query_logic); - g_test_add_func ("/mu-query/test-mu-query-accented-chars-1", - test_mu_query_accented_chars_01); - g_test_add_func ("/mu-query/test-mu-query-accented-chars-2", - test_mu_query_accented_chars_02); - g_test_add_func ("/mu-query/test-mu-query-accented-chars-fraiche", - test_mu_query_accented_chars_fraiche); + g_test_add_func("/mu-query/test-mu-query-accented-chars-1", + test_mu_query_accented_chars_01); + g_test_add_func("/mu-query/test-mu-query-accented-chars-2", + test_mu_query_accented_chars_02); + g_test_add_func("/mu-query/test-mu-query-accented-chars-fraiche", + test_mu_query_accented_chars_fraiche); - g_test_add_func ("/mu-query/test-mu-query-msgid", - test_mu_query_msgid); + g_test_add_func("/mu-query/test-mu-query-msgid", test_mu_query_msgid); - g_test_add_func ("/mu-query/test-mu-query-wom-bat", - test_mu_query_wom_bat); + g_test_add_func("/mu-query/test-mu-query-wom-bat", test_mu_query_wom_bat); - g_test_add_func ("/mu-query/test-mu-query-wildcards", - test_mu_query_wildcards); - g_test_add_func ("/mu-query/test-mu-query-sizes", - test_mu_query_sizes); + g_test_add_func("/mu-query/test-mu-query-wildcards", test_mu_query_wildcards); + g_test_add_func("/mu-query/test-mu-query-sizes", test_mu_query_sizes); - g_test_add_func ("/mu-query/test-mu-query-dates-helsinki", - test_mu_query_dates_helsinki); - g_test_add_func ("/mu-query/test-mu-query-dates-sydney", - test_mu_query_dates_sydney); - g_test_add_func ("/mu-query/test-mu-query-dates-la", - test_mu_query_dates_la); + g_test_add_func("/mu-query/test-mu-query-dates-helsinki", test_mu_query_dates_helsinki); + g_test_add_func("/mu-query/test-mu-query-dates-sydney", test_mu_query_dates_sydney); + g_test_add_func("/mu-query/test-mu-query-dates-la", test_mu_query_dates_la); - g_test_add_func ("/mu-query/test-mu-query-attach", - test_mu_query_attach); - g_test_add_func ("/mu-query/test-mu-query-tags", - test_mu_query_tags); - g_test_add_func ("/mu-query/test-mu-query-tags_02", - test_mu_query_tags_02); + g_test_add_func("/mu-query/test-mu-query-attach", test_mu_query_attach); + g_test_add_func("/mu-query/test-mu-query-tags", test_mu_query_tags); + g_test_add_func("/mu-query/test-mu-query-tags_02", test_mu_query_tags_02); - g_test_add_func ("/mu-query/test-mu-query-threads-compilation-error", - test_mu_query_threads_compilation_error); + g_test_add_func("/mu-query/test-mu-query-threads-compilation-error", + test_mu_query_threads_compilation_error); if (!g_test_verbose()) - g_log_set_handler (NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| - G_LOG_LEVEL_WARNING|G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, NULL); - rv = g_test_run (); + g_log_set_handler(NULL, + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | + G_LOG_LEVEL_WARNING | G_LOG_FLAG_RECURSION), + (GLogFunc)black_hole, + NULL); + rv = g_test_run(); return rv; } diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el index 839b0461..9cdd9ede 100644 --- a/mu4e/mu4e-draft.el +++ b/mu4e/mu4e-draft.el @@ -347,16 +347,17 @@ one. Code borrowed from `message-shorten-1'." (defun mu4e~fontify-signature () - "Give the message signatures a distinctive color. This is used in -the view and compose modes and will color each signature in digest messages adhering to RFC 1153." + "Give the message signatures a distinctive color. This is used +in the view and compose modes and will color each signature in +digest messages adhering to RFC 1153." (let ((inhibit-read-only t)) (save-excursion ;; give the footer a different color... (goto-char (point-min)) (while (re-search-forward "^-- *$" nil t) (let ((p (point)) - (end (or - (re-search-forward "\\(^-\\{30\\}.*$\\)" nil t) ;; 30 by RFC1153 + (end (or ;; 30 by RFC1153 + (re-search-forward "\\(^-\\{30\\}.*$\\)" nil t) (point-max)))) (add-text-properties p end '(face mu4e-footer-face))))))) diff --git a/mu4e/mu4e-headers.el b/mu4e/mu4e-headers.el index 30b9a1f9..4d0df787 100644 --- a/mu4e/mu4e-headers.el +++ b/mu4e/mu4e-headers.el @@ -354,8 +354,8 @@ headers." ;; search results) ;; since we still have the search results, re-use ;; those - (plist-put msg :thread - (mu4e~headers-field-for-docid docid :thread)) + (plist-put msg :meta + (mu4e~headers-field-for-docid docid :meta)) ;; first, remove the old one (otherwise, we'd have two headers with ;; the same docid... @@ -617,7 +617,7 @@ date. The formats used for date and time are "Get the subject if it is the first one in a thread; otherwise, return the thread-prefix without the subject-text. In other words, show the subject of a thread only once, similar to e.g. 'mutt'." - (let* ((tinfo (mu4e-message-field msg :thread)) + (let* ((tinfo (mu4e-message-field msg :meta)) (subj (mu4e-msg-field msg :subject))) (concat ;; prefix subject with a thread indicator (mu4e~headers-thread-prefix tinfo) @@ -645,8 +645,8 @@ found." (cl-case field (:subject (concat ;; prefix subject with a thread indicator - (mu4e~headers-thread-prefix (mu4e-message-field msg :thread)) - ;; "["(plist-get (mu4e-message-field msg :thread) :path) "] " + (mu4e~headers-thread-prefix (mu4e-message-field msg :meta)) + ;; "["(plist-get (mu4e-message-field msg :meta) :path) "] " ;; work-around: emacs' display gets really slow when lines are too long; ;; so limit subject length to 600 (truncate-string-to-width val 600))) @@ -1376,9 +1376,9 @@ matching messages with that mark." (defun mu4e~headers-get-thread-info (msg what) "Get WHAT (a symbol, either path or thread-id) for MSG." - (let* ((thread (or (mu4e-message-field msg :thread) + (let* ((meta (or (mu4e-message-field msg :meta) (mu4e-error "No thread info found"))) - (path (or (plist-get thread :path) + (path (or (plist-get meta :path) (mu4e-error "No threadpath found")))) (cl-case what (path path) diff --git a/mu4e/mu4e-message.el b/mu4e/mu4e-message.el index c82e64cb..b8d01db6 100644 --- a/mu4e/mu4e-message.el +++ b/mu4e/mu4e-message.el @@ -1,4 +1,4 @@ -;;; mu4e-message.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*- +;;; mu4e-message.el -- part of mu4e -*- lexical-binding: t -*- ;; Copyright (C) 2012-2020 Dirk-Jan C. Binnema @@ -97,7 +97,8 @@ Like `mu4e-message-field-nil', but will sanitize nil values: - all string field except body-txt/body-html: nil -> \"\" - numeric fields + dates : nil -> 0 - all others : return the value -Thus, function will return nil for empty lists, non-existing body-txt or body-html." +Thus, function will return nil for empty lists, non-existing body-txt +or body-html." (let ((val (mu4e-message-field-raw msg field))) (cond (val diff --git a/mu4e/mu4e-search.el b/mu4e/mu4e-search.el index 43d70aac..e0f9aea4 100644 --- a/mu4e/mu4e-search.el +++ b/mu4e/mu4e-search.el @@ -164,7 +164,7 @@ show the message with MSGID." (interactive) (mu4e-search mu4e--search-last-query nil t)) -(define-obsolete-variable-alias 'mu4e-headers-search-edit +(define-obsolete-function-alias 'mu4e-headers-search-edit 'mu4e-search-edit "1.7.0") (defun mu4e-search-bookmark (&optional expr edit) @@ -412,10 +412,10 @@ either `future' or `past'." (match-end 1) '("attach" "draft" "flagged" "list" "new" "passed" "replied" "seen" "trashed" "unread" "encrypted" "signed"))) - ;; ((looking-back "maildir:\\([a-zA-Z0-9/.]*\\)" nil) - ;; (list (match-beginning 1) - ;; (match-end 1) - ;; (mu4e-get-maildirs))) + ((looking-back "maildir:\\([a-zA-Z0-9/.]*\\)" nil) + (list (match-beginning 1) + (match-end 1) + (mu4e-get-maildirs))) ((looking-back "prio:\\(\\w*\\)" nil) (list (match-beginning 1) (match-end 1) diff --git a/mu4e/mu4e-server.el b/mu4e/mu4e-server.el index 226b194e..1917b0f9 100644 --- a/mu4e/mu4e-server.el +++ b/mu4e/mu4e-server.el @@ -192,6 +192,16 @@ removed." (car objcons))))))) +(defsubst mu4e--message (msgdata) + "Convert MSGDATA into a msg plist. +This receives a 'message-data' blob of the form + (:meta (...) :message (...)) +and turns it into (:message :meta (...) ... ). + +The former version is what the server is optimized for, +but the latter is what the header wants." + (plist-put (plist-get msgdata :message) :meta (plist-get msgdata :meta))) + (defun mu4e--server-filter (_proc str) "Filter string STR from PROC. This processes the 'mu server' output. It accumulates the @@ -205,28 +215,27 @@ The server output is as follows: ;; eox => passed to `mu4e-error-func'. - 2a. a message sexp looks something like: - \( - :docid 1585 - :from ((\"Donald Duck\" . \"donald@example.com\")) - :to ((\"Mickey Mouse\" . \"mickey@example.com\")) - :subject \"Wicked stuff\" - :date (20023 26572 0) - :size 15165 - :references (\"200208121222.g7CCMdb80690@msg.id\") - :in-reply-to \"200208121222.g7CCMdb80690@msg.id\" - :message-id \"foobar32423847ef23@pluto.net\" - :maildir: \"/archive\" - :path \"/home/mickey/Maildir/inbox/cur/1312254065_3.32282.pluto,4cd5bd4e9:2,\" - :priority high - :flags (new unread) - :attachments ((2 \"hello.jpg\" \"image/jpeg\") (3 \"laah.mp3\" \"audio/mp3\")) - :body-txt \" \" -\) + 2a. a header exp looks something like: + (:header + :meta (....) + :message ( + :docid 1585 + :from ((\"Donald Duck\" . \"donald@example.com\")) + :to ((\"Mickey Mouse\" . \"mickey@example.com\")) + :subject \"Wicked stuff\" + :date (20023 26572 0) + :size 15165 + :references (\"200208121222.g7CCMdb80690@msg.id\") + :in-reply-to \"200208121222.g7CCMdb80690@msg.id\" + :message-id \"foobar32423847ef23@pluto.net\" + :maildir: \"/archive\" + :path \"/home/mickey/Maildir/inbox/cur/1312_3.32282.pluto,4cd5bd4e9:2,\" + :priority high + :flags (new unread))) ;; eox => this will be passed to `mu4e-header-func'. - 2b. After the list of message sexps has been returned (see 2a.), + 2b. After the list of headers has been returned (see 2a.), we'll receive a sexp that looks like (:found ) with n the number of messages found. The will be passed to `mu4e-found-func'. @@ -234,9 +243,11 @@ The server output is as follows: 3. a view looks like: (:view ) => the (see 2.) will be passed to `mu4e-view-func'. + like :header, but the :message also contains :body-txt and/or :body-html 4. a database update looks like: (:update :move ) + like :header => the (see 2.) will be passed to `mu4e-update-func', :move tells us whether this is a move to @@ -248,7 +259,7 @@ The server output is as follows: 6. a compose looks like: (:compose [:original] [:include ]) - `mu4e-compose-func'." + `mu4e-compose-func'. :original looks like :view." (mu4e-log 'misc "* Received %d byte(s)" (length str)) (setq mu4e--server-buf (concat mu4e--server-buf str)) ;; update our buffer (let ((sexp (mu4e--server-eat-sexp-from-buf))) @@ -257,8 +268,8 @@ The server output is as follows: (mu4e-log 'from-server "%S" sexp) (cond ;; a header plist can be recognized by the existence of a :date field - ((plist-get sexp :date) - (funcall mu4e-header-func sexp)) + ((plist-get sexp :header) + (funcall mu4e-header-func (mu4e--message (plist-get sexp :header)))) ;; the found sexp, we receive after getting all the headers ((plist-get sexp :found) @@ -266,7 +277,7 @@ The server output is as follows: ;; viewing a specific message ((plist-get sexp :view) - (funcall mu4e-view-func (plist-get sexp :view))) + (funcall mu4e-view-func (mu4e--message (plist-get sexp :view)))) ;; receive an erase message ((plist-get sexp :erase) @@ -293,7 +304,7 @@ The server output is as follows: ;; something got moved/flags changed ((plist-get sexp :update) (funcall mu4e-update-func - (plist-get sexp :update) + (mu4e--message (plist-get sexp :update)) (plist-get sexp :move) (plist-get sexp :maybe-view))) @@ -305,7 +316,7 @@ The server output is as follows: ((plist-get sexp :compose) (funcall mu4e-compose-func (plist-get sexp :compose) - (plist-get sexp :original) + (mu4e--message (plist-get sexp :original)) (plist-get sexp :include))) ;; get some info diff --git a/mu4e/mu4e-view.el b/mu4e/mu4e-view.el index ad620d7d..41323a54 100644 --- a/mu4e/mu4e-view.el +++ b/mu4e/mu4e-view.el @@ -310,7 +310,7 @@ selection." (mu4e~view-in-headers-context (mu4e-search-narrow))) (defun mu4e-view-search-edit () - "Run `mu4e-headers-search-edit' in the headers buffer." + "Run `mu4e-search-edit' in the headers buffer." (interactive) (mu4e~view-in-headers-context (mu4e-search-edit))) diff --git a/toys/mug/mu-msg-attach-view.cc b/toys/mug/mu-msg-attach-view.cc index 02972fed..82a7ae7b 100644 --- a/toys/mug/mu-msg-attach-view.cc +++ b/toys/mug/mu-msg-attach-view.cc @@ -32,11 +32,10 @@ enum { NUM_COL }; - /* 'private'/'protected' functions */ -static void mu_msg_attach_view_class_init (MuMsgAttachViewClass *klass); -static void mu_msg_attach_view_init (MuMsgAttachView *obj); -static void mu_msg_attach_view_finalize (GObject *obj); +static void mu_msg_attach_view_class_init(MuMsgAttachViewClass* klass); +static void mu_msg_attach_view_init(MuMsgAttachView* obj); +static void mu_msg_attach_view_finalize(GObject* obj); /* list my signals */ enum { @@ -46,254 +45,247 @@ enum { }; struct _MuMsgAttachViewPrivate { - MuMsg *_msg; + MuMsg* _msg; }; -#define MU_MSG_ATTACH_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MU_TYPE_MSG_ATTACH_VIEW, \ - MuMsgAttachViewPrivate)) +#define MU_MSG_ATTACH_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MU_TYPE_MSG_ATTACH_VIEW, MuMsgAttachViewPrivate)) /* globals */ -static GtkIconViewClass *parent_class = NULL; +static GtkIconViewClass* parent_class = NULL; static guint signals[LAST_SIGNAL] = {0}; -G_DEFINE_TYPE (MuMsgAttachView, mu_msg_attach_view, GTK_TYPE_ICON_VIEW); - +G_DEFINE_TYPE(MuMsgAttachView, mu_msg_attach_view, GTK_TYPE_ICON_VIEW); static void -set_message (MuMsgAttachView *self, MuMsg *msg) +set_message(MuMsgAttachView* self, MuMsg* msg) { if (self->_priv->_msg == msg) return; /* nothing to todo */ - if (self->_priv->_msg) { - mu_msg_unref (self->_priv->_msg); + if (self->_priv->_msg) { + mu_msg_unref(self->_priv->_msg); self->_priv->_msg = NULL; } if (msg) - self->_priv->_msg = mu_msg_ref (msg); + self->_priv->_msg = mu_msg_ref(msg); } - static void -mu_msg_attach_view_class_init (MuMsgAttachViewClass *klass) +mu_msg_attach_view_class_init(MuMsgAttachViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkIconViewClass*)g_type_class_peek_parent (klass); + parent_class = (GtkIconViewClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mu_msg_attach_view_finalize; - g_type_class_add_private (gobject_class, sizeof(MuMsgAttachViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MuMsgAttachViewPrivate)); signals[ATTACH_ACTIVATED] = - g_signal_new ("attach-activated", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MuMsgAttachViewClass, - attach_activated), - NULL, NULL, - g_cclosure_marshal_VOID__UINT_POINTER, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); + g_signal_new("attach-activated", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MuMsgAttachViewClass, attach_activated), + NULL, + NULL, + g_cclosure_marshal_VOID__UINT_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_POINTER); } static void -item_activated (MuMsgAttachView *self, GtkTreePath *tpath) +item_activated(MuMsgAttachView* self, GtkTreePath* tpath) { - GtkTreeModel *model; - GtkTreeIter iter; - guint partnum; + GtkTreeModel* model; + GtkTreeIter iter; + guint partnum; - model = gtk_icon_view_get_model (GTK_ICON_VIEW(self)); - if (!gtk_tree_model_get_iter (model, &iter, tpath)) { - g_warning ("could not find path"); + model = gtk_icon_view_get_model(GTK_ICON_VIEW(self)); + if (!gtk_tree_model_get_iter(model, &iter, tpath)) { + g_warning("could not find path"); } - gtk_tree_model_get (model, &iter, - PARTNUM_COL, &partnum, - -1); + gtk_tree_model_get(model, &iter, PARTNUM_COL, &partnum, -1); - g_signal_emit (G_OBJECT (self), - signals[ATTACH_ACTIVATED], 0, - partnum, self->_priv->_msg); + g_signal_emit(G_OBJECT(self), signals[ATTACH_ACTIVATED], 0, partnum, self->_priv->_msg); } static void -accumulate_parts (MuMsgAttachView *self, GtkTreePath *path, GSList **lst) +accumulate_parts(MuMsgAttachView* self, GtkTreePath* path, GSList** lst) { - GtkTreeIter iter; - GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeModel* model; /* don't unref */ - model = gtk_icon_view_get_model (GTK_ICON_VIEW(self)); + model = gtk_icon_view_get_model(GTK_ICON_VIEW(self)); - if (gtk_tree_model_get_iter (model, &iter, path)) { - gchar *filepath; - gint idx; - gtk_tree_model_get (model, &iter, PARTNUM_COL, &idx, -1); - filepath = mu_msg_part_get_cache_path (self->_priv->_msg, - MU_MSG_OPTION_NONE, - idx, NULL); + if (gtk_tree_model_get_iter(model, &iter, path)) { + gchar* filepath; + gint idx; + gtk_tree_model_get(model, &iter, PARTNUM_COL, &idx, -1); + filepath = + mu_msg_part_get_cache_path(self->_priv->_msg, MU_MSG_OPTION_NONE, idx, NULL); if (filepath) { - if (mu_msg_part_save (self->_priv->_msg, - MU_MSG_OPTION_USE_EXISTING, - filepath, - idx, NULL)) { - GFile *file; - file = g_file_new_for_path (filepath); - *lst = g_slist_prepend (*lst, g_file_get_uri(file)); - g_object_unref (file); + if (mu_msg_part_save(self->_priv->_msg, + MU_MSG_OPTION_USE_EXISTING, + filepath, + idx, + NULL)) { + GFile* file; + file = g_file_new_for_path(filepath); + *lst = g_slist_prepend(*lst, g_file_get_uri(file)); + g_object_unref(file); } else - g_warning ("error saving msg part"); - g_free (filepath); + g_warning("error saving msg part"); + g_free(filepath); } } } - - static void -on_drag_data_get (MuMsgAttachView *self, GdkDragContext *drag_context, - GtkSelectionData *data, guint info, guint time, gpointer user_data) +on_drag_data_get(MuMsgAttachView* self, + GdkDragContext* drag_context, + GtkSelectionData* data, + guint info, + guint time, + gpointer user_data) { GSList *lst, *cur; - char **uris; - int i; + char** uris; + int i; lst = NULL; - gtk_icon_view_selected_foreach (GTK_ICON_VIEW(self), - (GtkIconViewForeachFunc)accumulate_parts, - &lst); + gtk_icon_view_selected_foreach(GTK_ICON_VIEW(self), + (GtkIconViewForeachFunc)accumulate_parts, + &lst); uris = g_new(char*, g_slist_length(lst) + 1); for (cur = lst, i = 0; cur; cur = g_slist_next(cur)) uris[i++] = (gchar*)cur->data; uris[i] = NULL; - gtk_selection_data_set_uris (data, uris); + gtk_selection_data_set_uris(data, uris); - g_free (uris); - g_slist_free_full (lst, g_free); + g_free(uris); + g_slist_free_full(lst, g_free); } static void -mu_msg_attach_view_init (MuMsgAttachView *obj) +mu_msg_attach_view_init(MuMsgAttachView* obj) { - GtkListStore *store; + GtkListStore* store; - obj->_priv = MU_MSG_ATTACH_VIEW_GET_PRIVATE(obj); + obj->_priv = MU_MSG_ATTACH_VIEW_GET_PRIVATE(obj); obj->_priv->_msg = NULL; - store = gtk_list_store_new (NUM_COL,GDK_TYPE_PIXBUF, - G_TYPE_STRING, G_TYPE_UINT); - gtk_icon_view_set_model (GTK_ICON_VIEW(obj), GTK_TREE_MODEL(store)); - g_object_unref (store); + store = gtk_list_store_new(NUM_COL, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT); + gtk_icon_view_set_model(GTK_ICON_VIEW(obj), GTK_TREE_MODEL(store)); + g_object_unref(store); - gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW(obj), ICON_COL); - gtk_icon_view_set_text_column (GTK_ICON_VIEW(obj), NAME_COL); + gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(obj), ICON_COL); + gtk_icon_view_set_text_column(GTK_ICON_VIEW(obj), NAME_COL); - gtk_icon_view_set_margin (GTK_ICON_VIEW(obj), 0); - gtk_icon_view_set_spacing (GTK_ICON_VIEW(obj), 0); - gtk_icon_view_set_item_padding (GTK_ICON_VIEW(obj), 0); + gtk_icon_view_set_margin(GTK_ICON_VIEW(obj), 0); + gtk_icon_view_set_spacing(GTK_ICON_VIEW(obj), 0); + gtk_icon_view_set_item_padding(GTK_ICON_VIEW(obj), 0); /* note: only since GTK+ 2.22 */ /* gtk_icon_view_set_item_orientation (GTK_ICON_VIEW(obj), */ /* GTK_ORIENTATION_HORIZONTAL); */ - g_signal_connect (G_OBJECT(obj), "item-activated", - G_CALLBACK(item_activated), NULL); + g_signal_connect(G_OBJECT(obj), "item-activated", G_CALLBACK(item_activated), NULL); - gtk_icon_view_set_selection_mode (GTK_ICON_VIEW(obj), - GTK_SELECTION_MULTIPLE); + gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(obj), GTK_SELECTION_MULTIPLE); /* drag & drop */ - gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW(obj), - (GdkModifierType)0, NULL, 0, - GDK_ACTION_COPY); + gtk_icon_view_enable_model_drag_source(GTK_ICON_VIEW(obj), + (GdkModifierType)0, + NULL, + 0, + GDK_ACTION_COPY); gtk_drag_source_add_uri_targets(GTK_WIDGET(obj)); - g_signal_connect (obj, "drag-data-get", G_CALLBACK(on_drag_data_get), NULL); + g_signal_connect(obj, "drag-data-get", G_CALLBACK(on_drag_data_get), NULL); } - static void -mu_msg_attach_view_finalize (GObject *obj) +mu_msg_attach_view_finalize(GObject* obj) { - set_message (MU_MSG_ATTACH_VIEW(obj), NULL); + set_message(MU_MSG_ATTACH_VIEW(obj), NULL); - G_OBJECT_CLASS(parent_class)->finalize (obj); + G_OBJECT_CLASS(parent_class)->finalize(obj); } GtkWidget* -mu_msg_attach_view_new (void) +mu_msg_attach_view_new(void) { return GTK_WIDGET(g_object_new(MU_TYPE_MSG_ATTACH_VIEW, NULL)); } struct _CBData { - GtkListStore *store; - guint count; + GtkListStore* store; + guint count; }; typedef struct _CBData CBData; - - static void -each_part (MuMsg *msg, MuMsgPart *part, CBData *cbdata) +each_part(MuMsg* msg, MuMsgPart* part, CBData* cbdata) { GtkTreeIter treeiter; - GdkPixbuf *pixbuf; - char ctype[128]; + GdkPixbuf* pixbuf; + char ctype[128]; if (!mu_msg_part_maybe_attachment(part)) return; if (!part->type || !part->subtype) - snprintf (ctype, sizeof(ctype), "%s", - "application/octet-stream"); + snprintf(ctype, sizeof(ctype), "%s", "application/octet-stream"); else - snprintf (ctype, sizeof(ctype), "%s/%s", - part->type, part->subtype); + snprintf(ctype, sizeof(ctype), "%s/%s", part->type, part->subtype); - pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type (ctype, 16); + pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type(ctype, 16); if (!pixbuf) { - g_debug ("%s: could not get icon pixbuf for '%s'", - __func__, ctype); - pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type - ("application/octet-stream", 16); + g_debug("%s: could not get icon pixbuf for '%s'", __func__, ctype); + pixbuf = + mu_widget_util_get_icon_pixbuf_for_content_type("application/octet-stream", 16); } - gtk_list_store_append (cbdata->store, &treeiter); - gtk_list_store_set (cbdata->store, &treeiter, - NAME_COL, mu_msg_part_get_filename (part, TRUE), - ICON_COL, pixbuf, - PARTNUM_COL, part->index, - -1); + gtk_list_store_append(cbdata->store, &treeiter); + gtk_list_store_set(cbdata->store, + &treeiter, + NAME_COL, + mu_msg_part_get_filename(part, TRUE), + ICON_COL, + pixbuf, + PARTNUM_COL, + part->index, + -1); if (pixbuf) - g_object_unref (pixbuf); + g_object_unref(pixbuf); ++cbdata->count; } gint -mu_msg_attach_view_set_message (MuMsgAttachView *self, MuMsg *msg) +mu_msg_attach_view_set_message(MuMsgAttachView* self, MuMsg* msg) { - GtkListStore *store; - CBData cbdata; + GtkListStore* store; + CBData cbdata; - g_return_val_if_fail (MU_IS_MSG_ATTACH_VIEW(self), -1); + g_return_val_if_fail(MU_IS_MSG_ATTACH_VIEW(self), -1); - store = GTK_LIST_STORE (gtk_icon_view_get_model (GTK_ICON_VIEW(self))); - gtk_list_store_clear (store); + store = GTK_LIST_STORE(gtk_icon_view_get_model(GTK_ICON_VIEW(self))); + gtk_list_store_clear(store); - set_message (self, msg); + set_message(self, msg); if (!msg) return 0; - cbdata.store = store; cbdata.count = 0; - mu_msg_part_foreach (msg, MU_MSG_OPTION_NONE, - (MuMsgPartForeachFunc)each_part, &cbdata); + mu_msg_part_foreach(msg, MU_MSG_OPTION_NONE, (MuMsgPartForeachFunc)each_part, &cbdata); return cbdata.count; } diff --git a/toys/mug/mu-msg-attach-view.hh b/toys/mug/mu-msg-attach-view.hh index 34a8bd5c..3a9360dc 100644 --- a/toys/mug/mu-msg-attach-view.hh +++ b/toys/mug/mu-msg-attach-view.hh @@ -17,7 +17,6 @@ ** */ - #ifndef MU_MSG_ATTACH_VIEW_HH__ #define MU_MSG_ATTACH_VIEW_HH__ @@ -27,40 +26,43 @@ G_BEGIN_DECLS /* convenience macros */ -#define MU_TYPE_MSG_ATTACH_VIEW (mu_msg_attach_view_get_type()) -#define MU_MSG_ATTACH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_ATTACH_VIEW,MuMsgAttachView)) -#define MU_MSG_ATTACH_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_ATTACH_VIEW,MuMsgAttachViewClass)) -#define MU_IS_MSG_ATTACH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_ATTACH_VIEW)) -#define MU_IS_MSG_ATTACH_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_ATTACH_VIEW)) -#define MU_MSG_ATTACH_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_ATTACH_VIEW,MuMsgAttachViewClass)) +#define MU_TYPE_MSG_ATTACH_VIEW (mu_msg_attach_view_get_type()) +#define MU_MSG_ATTACH_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MU_TYPE_MSG_ATTACH_VIEW, MuMsgAttachView)) +#define MU_MSG_ATTACH_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MU_TYPE_MSG_ATTACH_VIEW, MuMsgAttachViewClass)) +#define MU_IS_MSG_ATTACH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), MU_TYPE_MSG_ATTACH_VIEW)) +#define MU_IS_MSG_ATTACH_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), MU_TYPE_MSG_ATTACH_VIEW)) +#define MU_MSG_ATTACH_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MU_TYPE_MSG_ATTACH_VIEW, MuMsgAttachViewClass)) -typedef struct _MuMsgAttachView MuMsgAttachView; -typedef struct _MuMsgAttachViewClass MuMsgAttachViewClass; -typedef struct _MuMsgAttachViewPrivate MuMsgAttachViewPrivate; +typedef struct _MuMsgAttachView MuMsgAttachView; +typedef struct _MuMsgAttachViewClass MuMsgAttachViewClass; +typedef struct _MuMsgAttachViewPrivate MuMsgAttachViewPrivate; struct _MuMsgAttachView { - GtkIconView parent; + GtkIconView parent; /* insert public members, if any */ /* private */ - MuMsgAttachViewPrivate *_priv; + MuMsgAttachViewPrivate* _priv; }; struct _MuMsgAttachViewClass { GtkIconViewClass parent_class; - void (* attach_activated) (MuMsgAttachView* obj, guint partnum, - Mu::MuMsg *msg); + void (*attach_activated)(MuMsgAttachView* obj, guint partnum, Mu::MuMsg* msg); }; /* member functions */ -GType mu_msg_attach_view_get_type (void) G_GNUC_CONST; +GType mu_msg_attach_view_get_type(void) G_GNUC_CONST; /* parameter-less _new function (constructor) */ /* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mu_msg_attach_view_new (void); +GtkWidget* mu_msg_attach_view_new(void); /* returns # of attachments */ -int mu_msg_attach_view_set_message (MuMsgAttachView *self, Mu::MuMsg *msg); +int mu_msg_attach_view_set_message(MuMsgAttachView* self, Mu::MuMsg* msg); G_END_DECLS diff --git a/toys/mug/mu-msg-body-view.cc b/toys/mug/mu-msg-body-view.cc index c2626755..4bfed83d 100644 --- a/toys/mug/mu-msg-body-view.cc +++ b/toys/mug/mu-msg-body-view.cc @@ -32,9 +32,9 @@ enum _ViewMode { typedef enum _ViewMode ViewMode; /* 'private'/'protected' functions */ -static void mu_msg_body_view_class_init (MuMsgBodyViewClass *klass); -static void mu_msg_body_view_init (MuMsgBodyView *obj); -static void mu_msg_body_view_finalize (GObject *obj); +static void mu_msg_body_view_class_init(MuMsgBodyViewClass* klass); +static void mu_msg_body_view_init(MuMsgBodyView* obj); +static void mu_msg_body_view_finalize(GObject* obj); /* list my signals */ enum { @@ -43,91 +43,92 @@ enum { LAST_SIGNAL }; - struct _MuMsgBodyViewPrivate { - WebKitSettings *_settings; - MuMsg *_msg; - ViewMode _view_mode; + WebKitSettings* _settings; + MuMsg* _msg; + ViewMode _view_mode; }; -#define MU_MSG_BODY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MU_TYPE_MSG_BODY_VIEW, \ - MuMsgBodyViewPrivate)) +#define MU_MSG_BODY_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MU_TYPE_MSG_BODY_VIEW, MuMsgBodyViewPrivate)) /* globals */ -static WebKitWebViewClass *parent_class = NULL; +static WebKitWebViewClass* parent_class = NULL; static guint signals[LAST_SIGNAL] = {0}; -G_DEFINE_TYPE (MuMsgBodyView, mu_msg_body_view, WEBKIT_TYPE_WEB_VIEW); +G_DEFINE_TYPE(MuMsgBodyView, mu_msg_body_view, WEBKIT_TYPE_WEB_VIEW); static void -set_message (MuMsgBodyView *self, MuMsg *msg) +set_message(MuMsgBodyView* self, MuMsg* msg) { if (self->_priv->_msg == msg) return; /* nothing to todo */ - if (self->_priv->_msg) { - mu_msg_unref (self->_priv->_msg); + if (self->_priv->_msg) { + mu_msg_unref(self->_priv->_msg); self->_priv->_msg = NULL; } if (msg) - self->_priv->_msg = mu_msg_ref (msg); + self->_priv->_msg = mu_msg_ref(msg); } static void -mu_msg_body_view_class_init (MuMsgBodyViewClass *klass) +mu_msg_body_view_class_init(MuMsgBodyViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (WebKitWebViewClass*)g_type_class_peek_parent (klass); + parent_class = (WebKitWebViewClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mu_msg_body_view_finalize; - g_type_class_add_private (gobject_class, sizeof(MuMsgBodyViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MuMsgBodyViewPrivate)); signals[ACTION_REQUESTED] = - g_signal_new ("action-requested", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MuMsgBodyViewClass, - action_requested), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_signal_new("action-requested", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MuMsgBodyViewClass, action_requested), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); } static char* -save_file_for_cid (MuMsg *msg, const char* cid) +save_file_for_cid(MuMsg* msg, const char* cid) { - gint idx; - gchar *filepath; + gint idx; + gchar* filepath; gboolean rv; - GError *err; + GError* err; - g_return_val_if_fail (msg, NULL); - g_return_val_if_fail (cid, NULL); + g_return_val_if_fail(msg, NULL); + g_return_val_if_fail(cid, NULL); - idx = mu_msg_find_index_for_cid (msg, MU_MSG_OPTION_NONE, cid); + idx = mu_msg_find_index_for_cid(msg, MU_MSG_OPTION_NONE, cid); if (idx < 0) { - g_warning ("%s: cannot find %s", __func__, cid); + g_warning("%s: cannot find %s", __func__, cid); return NULL; } - filepath = mu_msg_part_get_cache_path (msg, MU_MSG_OPTION_NONE, idx, NULL); + filepath = mu_msg_part_get_cache_path(msg, MU_MSG_OPTION_NONE, idx, NULL); if (!filepath) { - g_warning ("%s: cannot create filepath", filepath); + g_warning("%s: cannot create filepath", filepath); return NULL; } err = NULL; - rv = mu_msg_part_save (msg, MU_MSG_OPTION_USE_EXISTING, - filepath, idx, &err); + rv = mu_msg_part_save(msg, MU_MSG_OPTION_USE_EXISTING, filepath, idx, &err); if (!rv) { - g_warning ("%s: failed to save %s: %s", __func__, filepath, - err&&err->message?err->message:"error"); - g_clear_error (&err); - g_free (filepath); + g_warning("%s: failed to save %s: %s", + __func__, + filepath, + err && err->message ? err->message : "error"); + g_clear_error(&err); + g_free(filepath); filepath = NULL; } @@ -135,82 +136,82 @@ save_file_for_cid (MuMsg *msg, const char* cid) } static void -on_resource_load_started (MuMsgBodyView *self, WebKitWebResource *resource, - WebKitURIRequest *request, gpointer data) +on_resource_load_started(MuMsgBodyView* self, + WebKitWebResource* resource, + WebKitURIRequest* request, + gpointer data) { - const char* uri; - MuMsg *msg; + const char* uri; + MuMsg* msg; msg = self->_priv->_msg; - uri = webkit_uri_request_get_uri (request); + uri = webkit_uri_request_get_uri(request); /* g_warning ("%s: %s", __func__, uri); */ - if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) { - gchar *filepath; - filepath = save_file_for_cid (msg, uri); + if (g_ascii_strncasecmp(uri, "cid:", 4) == 0) { + gchar* filepath; + filepath = save_file_for_cid(msg, uri); if (filepath) { - gchar *fileuri; - fileuri = g_strdup_printf ("file://%s", filepath); - webkit_uri_request_set_uri (request, fileuri); - g_free (fileuri); - g_free (filepath); + gchar* fileuri; + fileuri = g_strdup_printf("file://%s", filepath); + webkit_uri_request_set_uri(request, fileuri); + g_free(fileuri); + g_free(filepath); } } } - static void -on_menu_item_activate (GtkMenuItem *item, MuMsgBodyView *self) +on_menu_item_activate(GtkMenuItem* item, MuMsgBodyView* self) { - g_signal_emit (G_OBJECT(self), - signals[ACTION_REQUESTED], 0, - g_object_get_data (G_OBJECT(item), "action")); + g_signal_emit(G_OBJECT(self), + signals[ACTION_REQUESTED], + 0, + g_object_get_data(G_OBJECT(item), "action")); } static void -popup_menu (MuMsgBodyView *self, guint button, guint32 activate_time) +popup_menu(MuMsgBodyView* self, guint button, guint32 activate_time) { - GtkWidget *menu; - int i; + GtkWidget* menu; + int i; struct { const char* title; const char* action; - ViewMode mode; + ViewMode mode; } actions[] = { - { "View source...", "view-source", VIEW_MODE_MSG }, - { "View message...", "view-message", VIEW_MODE_SOURCE }, + {"View source...", "view-source", VIEW_MODE_MSG}, + {"View message...", "view-message", VIEW_MODE_SOURCE}, }; - menu = gtk_menu_new (); + menu = gtk_menu_new(); for (i = 0; i != G_N_ELEMENTS(actions); ++i) { - GtkWidget *item; + GtkWidget* item; if (self->_priv->_view_mode != actions[i].mode) continue; item = gtk_menu_item_new_with_label(actions[i].title); - g_object_set_data (G_OBJECT(item), "action", (gpointer)actions[i].action); - g_signal_connect (item, "activate", G_CALLBACK(on_menu_item_activate), - self); - gtk_menu_attach (GTK_MENU(menu), item, 0, 1, i, i+1); - gtk_widget_show (item); + g_object_set_data(G_OBJECT(item), "action", (gpointer)actions[i].action); + g_signal_connect(item, "activate", G_CALLBACK(on_menu_item_activate), self); + gtk_menu_attach(GTK_MENU(menu), item, 0, 1, i, i + 1); + gtk_widget_show(item); } - gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0); } - static gboolean -on_button_press_event (MuMsgBodyView *self, GdkEventButton *event, gpointer data) +on_button_press_event(MuMsgBodyView* self, GdkEventButton* event, gpointer data) { - /* ignore all but the first (typically, left) mouse button */ + /* ignore all but the first (typically, left) mouse button */ switch (event->button) { case 1: return FALSE; /* propagate, let widget handle it */ case 3: /* no popup menus for notes */ if (self->_priv->_view_mode != VIEW_MODE_NOTE) - popup_menu (self, event->button, event->time); + popup_menu(self, event->button, event->time); break; default: return TRUE; /* ignore */ } @@ -218,123 +219,116 @@ on_button_press_event (MuMsgBodyView *self, GdkEventButton *event, gpointer data return (event->button > 1) ? TRUE : FALSE; } - static void -mu_msg_body_view_init (MuMsgBodyView *obj) +mu_msg_body_view_init(MuMsgBodyView* obj) { obj->_priv = MU_MSG_BODY_VIEW_GET_PRIVATE(obj); - obj->_priv->_msg = NULL; + obj->_priv->_msg = NULL; obj->_priv->_view_mode = VIEW_MODE_NONE; - obj->_priv->_settings = webkit_settings_new (); - g_object_set (G_OBJECT(obj->_priv->_settings), - "enable-javascript", FALSE, - "auto-load-images", TRUE, - "enable-plugins", FALSE, - NULL); + obj->_priv->_settings = webkit_settings_new(); + g_object_set(G_OBJECT(obj->_priv->_settings), + "enable-javascript", + FALSE, + "auto-load-images", + TRUE, + "enable-plugins", + FALSE, + NULL); - webkit_web_view_set_settings (WEBKIT_WEB_VIEW(obj), obj->_priv->_settings); + webkit_web_view_set_settings(WEBKIT_WEB_VIEW(obj), obj->_priv->_settings); /* to support cid: */ - g_signal_connect (obj, "resource-load-started", - G_CALLBACK (on_resource_load_started), NULL); - g_signal_connect (obj, "button-press-event", - G_CALLBACK(on_button_press_event), NULL); + g_signal_connect(obj, "resource-load-started", G_CALLBACK(on_resource_load_started), NULL); + g_signal_connect(obj, "button-press-event", G_CALLBACK(on_button_press_event), NULL); } static void -mu_msg_body_view_finalize (GObject *obj) +mu_msg_body_view_finalize(GObject* obj) { - MuMsgBodyViewPrivate *priv; + MuMsgBodyViewPrivate* priv; priv = MU_MSG_BODY_VIEW_GET_PRIVATE(obj); if (priv && priv->_settings) - g_object_unref (priv->_settings); + g_object_unref(priv->_settings); - set_message (MU_MSG_BODY_VIEW(obj), NULL); + set_message(MU_MSG_BODY_VIEW(obj), NULL); - G_OBJECT_CLASS(parent_class)->finalize (obj); + G_OBJECT_CLASS(parent_class)->finalize(obj); } GtkWidget* -mu_msg_body_view_new (void) +mu_msg_body_view_new(void) { return GTK_WIDGET(g_object_new(MU_TYPE_MSG_BODY_VIEW, NULL)); } - static void -set_html (MuMsgBodyView *self, const char* html) +set_html(MuMsgBodyView* self, const char* html) { - g_return_if_fail (MU_IS_MSG_BODY_VIEW(self)); + g_return_if_fail(MU_IS_MSG_BODY_VIEW(self)); - webkit_web_view_load_html (WEBKIT_WEB_VIEW(self), - html ? html : "", - NULL); + webkit_web_view_load_html(WEBKIT_WEB_VIEW(self), html ? html : "", NULL); } static void -set_text (MuMsgBodyView *self, const char* txt) +set_text(MuMsgBodyView* self, const char* txt) { - g_return_if_fail (MU_IS_MSG_BODY_VIEW(self)); + g_return_if_fail(MU_IS_MSG_BODY_VIEW(self)); - webkit_web_view_load_plain_text (WEBKIT_WEB_VIEW(self), txt ? txt : ""); + webkit_web_view_load_plain_text(WEBKIT_WEB_VIEW(self), txt ? txt : ""); } void -mu_msg_body_view_set_message (MuMsgBodyView *self, MuMsg *msg) +mu_msg_body_view_set_message(MuMsgBodyView* self, MuMsg* msg) { const char* data; - g_return_if_fail (self); + g_return_if_fail(self); - set_message (self, msg); + set_message(self, msg); - data = msg ? mu_msg_get_body_html (msg, MU_MSG_OPTION_NONE) : ""; + data = msg ? mu_msg_get_body_html(msg, MU_MSG_OPTION_NONE) : ""; if (data) - set_html (self, data); + set_html(self, data); else - set_text (self, - mu_msg_get_body_text (msg, MU_MSG_OPTION_NONE)); + set_text(self, mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE)); self->_priv->_view_mode = VIEW_MODE_MSG; } - void -mu_msg_body_view_set_message_source (MuMsgBodyView *self, MuMsg *msg) +mu_msg_body_view_set_message_source(MuMsgBodyView* self, MuMsg* msg) { - const gchar *path; - gchar *data; + const gchar* path; + gchar* data; - g_return_if_fail (MU_IS_MSG_BODY_VIEW(self)); - g_return_if_fail (msg); + g_return_if_fail(MU_IS_MSG_BODY_VIEW(self)); + g_return_if_fail(msg); - set_message (self, NULL); + set_message(self, NULL); - path = msg ? mu_msg_get_path (msg) : NULL; + path = msg ? mu_msg_get_path(msg) : NULL; - if (path && g_file_get_contents (path, &data, NULL, NULL)) { - set_text (self, data); - g_free (data); + if (path && g_file_get_contents(path, &data, NULL, NULL)) { + set_text(self, data); + g_free(data); } else - set_text (self, ""); + set_text(self, ""); self->_priv->_view_mode = VIEW_MODE_SOURCE; } - - void -mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html) +mu_msg_body_view_set_note(MuMsgBodyView* self, const gchar* html) { - g_return_if_fail (self); - g_return_if_fail (html); + g_return_if_fail(self); + g_return_if_fail(html); - set_message (self, NULL); + set_message(self, NULL); - set_html (self, html); + set_html(self, html); self->_priv->_view_mode = VIEW_MODE_NOTE; } diff --git a/toys/mug/mu-msg-body-view.hh b/toys/mug/mu-msg-body-view.hh index f4d060fd..1bb582e8 100644 --- a/toys/mug/mu-msg-body-view.hh +++ b/toys/mug/mu-msg-body-view.hh @@ -26,43 +26,45 @@ G_BEGIN_DECLS /* convenience macros */ -#define MU_TYPE_MSG_BODY_VIEW (mu_msg_body_view_get_type()) -#define MU_MSG_BODY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_BODY_VIEW,MuMsgBodyView)) -#define MU_MSG_BODY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_BODY_VIEW,MuMsgBodyViewClass)) -#define MU_IS_MSG_BODY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_BODY_VIEW)) -#define MU_IS_MSG_BODY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_BODY_VIEW)) -#define MU_MSG_BODY_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_BODY_VIEW,MuMsgBodyViewClass)) - -typedef struct _MuMsgBodyView MuMsgBodyView; -typedef struct _MuMsgBodyViewClass MuMsgBodyViewClass; -typedef struct _MuMsgBodyViewPrivate MuMsgBodyViewPrivate; +#define MU_TYPE_MSG_BODY_VIEW (mu_msg_body_view_get_type()) +#define MU_MSG_BODY_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MU_TYPE_MSG_BODY_VIEW, MuMsgBodyView)) +#define MU_MSG_BODY_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MU_TYPE_MSG_BODY_VIEW, MuMsgBodyViewClass)) +#define MU_IS_MSG_BODY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), MU_TYPE_MSG_BODY_VIEW)) +#define MU_IS_MSG_BODY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), MU_TYPE_MSG_BODY_VIEW)) +#define MU_MSG_BODY_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MU_TYPE_MSG_BODY_VIEW, MuMsgBodyViewClass)) +typedef struct _MuMsgBodyView MuMsgBodyView; +typedef struct _MuMsgBodyViewClass MuMsgBodyViewClass; +typedef struct _MuMsgBodyViewPrivate MuMsgBodyViewPrivate; struct _MuMsgBodyView { - WebKitWebView parent; + WebKitWebView parent; /* insert public members, if any */ /* private */ - MuMsgBodyViewPrivate *_priv; + MuMsgBodyViewPrivate* _priv; }; struct _MuMsgBodyViewClass { WebKitWebViewClass parent_class; /* supported actions: "reindex", "view-source" */ - void (* action_requested) (MuMsgBodyView* self, const char* action); + void (*action_requested)(MuMsgBodyView* self, const char* action); }; /* member functions */ -GType mu_msg_body_view_get_type (void) G_GNUC_CONST; +GType mu_msg_body_view_get_type(void) G_GNUC_CONST; /* parameter-less _new function (constructor) */ /* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mu_msg_body_view_new (void); +GtkWidget* mu_msg_body_view_new(void); -void mu_msg_body_view_set_message (MuMsgBodyView *self, Mu::MuMsg *msg); -void mu_msg_body_view_set_note (MuMsgBodyView *self, const gchar *html); -void mu_msg_body_view_set_message_source (MuMsgBodyView *self, Mu::MuMsg *msg); +void mu_msg_body_view_set_message(MuMsgBodyView* self, Mu::MuMsg* msg); +void mu_msg_body_view_set_note(MuMsgBodyView* self, const gchar* html); +void mu_msg_body_view_set_message_source(MuMsgBodyView* self, Mu::MuMsg* msg); G_END_DECLS diff --git a/toys/mug/mu-msg-header-view.cc b/toys/mug/mu-msg-header-view.cc index ab5c5d75..be3dfd73 100644 --- a/toys/mug/mu-msg-header-view.cc +++ b/toys/mug/mu-msg-header-view.cc @@ -26,9 +26,9 @@ using namespace Mu; /* 'private'/'protected' functions */ -static void mu_msg_header_view_class_init (MuMsgHeaderViewClass *klass); -static void mu_msg_header_view_init (MuMsgHeaderView *obj); -static void mu_msg_header_view_finalize (GObject *obj); +static void mu_msg_header_view_class_init(MuMsgHeaderViewClass* klass); +static void mu_msg_header_view_init(MuMsgHeaderView* obj); +static void mu_msg_header_view_finalize(GObject* obj); /* list my signals */ enum { @@ -38,150 +38,142 @@ enum { }; struct _MuMsgHeaderViewPrivate { - GtkWidget *_grid; + GtkWidget* _grid; }; -#define MU_MSG_HEADER_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MU_TYPE_MSG_HEADER_VIEW, \ - MuMsgHeaderViewPrivate)) +#define MU_MSG_HEADER_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MU_TYPE_MSG_HEADER_VIEW, MuMsgHeaderViewPrivate)) /* globals */ -static GtkBoxClass *parent_class = NULL; +static GtkBoxClass* parent_class = NULL; /* uncomment the following if you have defined any signals */ /* static guint signals[LAST_SIGNAL] = {0}; */ -G_DEFINE_TYPE (MuMsgHeaderView, mu_msg_header_view, GTK_TYPE_BOX); - +G_DEFINE_TYPE(MuMsgHeaderView, mu_msg_header_view, GTK_TYPE_BOX); static void -mu_msg_header_view_class_init (MuMsgHeaderViewClass *klass) +mu_msg_header_view_class_init(MuMsgHeaderViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkBoxClass*)g_type_class_peek_parent (klass); + parent_class = (GtkBoxClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mu_msg_header_view_finalize; - g_type_class_add_private (gobject_class, sizeof(MuMsgHeaderViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MuMsgHeaderViewPrivate)); /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ + /* signals[MY_SIGNAL_1] = */ + /* g_signal_new ("my_signal_1",....); */ + /* signals[MY_SIGNAL_2] = */ + /* g_signal_new ("my_signal_2",....); */ + /* etc. */ } static void -mu_msg_header_view_init (MuMsgHeaderView *obj) +mu_msg_header_view_init(MuMsgHeaderView* obj) { - -/* static GtkBoxClass *parent_class = NULL; */ - obj->_priv = MU_MSG_HEADER_VIEW_GET_PRIVATE(obj); + /* static GtkBoxClass *parent_class = NULL; */ + obj->_priv = MU_MSG_HEADER_VIEW_GET_PRIVATE(obj); obj->_priv->_grid = NULL; } static void -mu_msg_header_view_finalize (GObject *obj) +mu_msg_header_view_finalize(GObject* obj) { - G_OBJECT_CLASS(parent_class)->finalize (obj); + G_OBJECT_CLASS(parent_class)->finalize(obj); } GtkWidget* -mu_msg_header_view_new (void) +mu_msg_header_view_new(void) { return GTK_WIDGET(g_object_new(MU_TYPE_MSG_HEADER_VIEW, NULL)); } - static GtkWidget* -get_label (const gchar *txt, gboolean istitle) +get_label(const gchar* txt, gboolean istitle) { - GtkWidget *label; + GtkWidget* label; - label = gtk_label_new (NULL); + label = gtk_label_new(NULL); if (istitle) { char* markup; - markup = g_strdup_printf ("%s: ", txt); - gtk_label_set_markup (GTK_LABEL(label), markup); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT); - g_free (markup); + markup = g_strdup_printf("%s: ", txt); + gtk_label_set_markup(GTK_LABEL(label), markup); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); + g_free(markup); } else { - gtk_label_set_selectable (GTK_LABEL (label), TRUE); - gtk_label_set_text (GTK_LABEL(label), txt ? txt : ""); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_label_set_text(GTK_LABEL(label), txt ? txt : ""); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); } return label; } G_GNUC_UNUSED static gboolean -add_row (GtkWidget *grid, guint row, const char* fieldname, const char *value, - gboolean showempty) +add_row(GtkWidget* grid, guint row, const char* fieldname, const char* value, gboolean showempty) { GtkWidget *label, *al; if (!value && !showempty) return FALSE; - gtk_grid_insert_row (GTK_GRID(grid), row); + gtk_grid_insert_row(GTK_GRID(grid), row); - label = get_label (fieldname, TRUE); - al = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); - gtk_container_add (GTK_CONTAINER (al), label); + label = get_label(fieldname, TRUE); + al = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); + gtk_container_add(GTK_CONTAINER(al), label); - gtk_grid_attach (GTK_GRID(grid), al, 0, row, 1, 1); + gtk_grid_attach(GTK_GRID(grid), al, 0, row, 1, 1); - al = gtk_alignment_new (0.0, 1.0, 0.0, 0.0); + al = gtk_alignment_new(0.0, 1.0, 0.0, 0.0); - label = get_label (value, FALSE); - gtk_container_add (GTK_CONTAINER (al), label); - gtk_grid_attach (GTK_GRID(grid), al, 1, row, 1, 1); + label = get_label(value, FALSE); + gtk_container_add(GTK_CONTAINER(al), label); + gtk_grid_attach(GTK_GRID(grid), al, 1, row, 1, 1); return TRUE; } - static GtkWidget* -get_grid (Mu::MuMsg *msg) +get_grid(Mu::MuMsg* msg) { - GtkWidget *grid; - int row; + GtkWidget* grid; + int row; - row = 0; - grid = gtk_grid_new (); /* 5 2 */ + row = 0; + grid = gtk_grid_new(); /* 5 2 */ - gtk_grid_insert_column (GTK_GRID(grid), 0); - gtk_grid_insert_column (GTK_GRID(grid), 1); + gtk_grid_insert_column(GTK_GRID(grid), 0); + gtk_grid_insert_column(GTK_GRID(grid), 1); - if (add_row (grid, row, "From", mu_msg_get_from (msg), TRUE)) + if (add_row(grid, row, "From", mu_msg_get_from(msg), TRUE)) ++row; - if (add_row (grid, row, "To", mu_msg_get_to (msg), FALSE)) + if (add_row(grid, row, "To", mu_msg_get_to(msg), FALSE)) ++row; - if (add_row (grid, row, "Cc", mu_msg_get_cc (msg), FALSE)) + if (add_row(grid, row, "Cc", mu_msg_get_cc(msg), FALSE)) ++row; - if (add_row (grid, row, "Subject", mu_msg_get_subject (msg), TRUE)) + if (add_row(grid, row, "Subject", mu_msg_get_subject(msg), TRUE)) ++row; - if (add_row (grid, row, "Date", mu_date_str_s - ("%c", mu_msg_get_date (msg)),TRUE)) + if (add_row(grid, row, "Date", mu_date_str_s("%c", mu_msg_get_date(msg)), TRUE)) ++row; return grid; } void -mu_msg_header_view_set_message (MuMsgHeaderView *self, Mu::MuMsg *msg) +mu_msg_header_view_set_message(MuMsgHeaderView* self, Mu::MuMsg* msg) { - g_return_if_fail (MU_IS_MSG_HEADER_VIEW(self)); + g_return_if_fail(MU_IS_MSG_HEADER_VIEW(self)); if (self->_priv->_grid) { - gtk_container_remove (GTK_CONTAINER(self), self->_priv->_grid); + gtk_container_remove(GTK_CONTAINER(self), self->_priv->_grid); self->_priv->_grid = NULL; } if (msg) { - self->_priv->_grid = get_grid (msg); - gtk_box_pack_start (GTK_BOX(self), self->_priv->_grid, - TRUE, TRUE, 0); - gtk_widget_show_all (self->_priv->_grid); + self->_priv->_grid = get_grid(msg); + gtk_box_pack_start(GTK_BOX(self), self->_priv->_grid, TRUE, TRUE, 0); + gtk_widget_show_all(self->_priv->_grid); } } diff --git a/toys/mug/mu-msg-header-view.hh b/toys/mug/mu-msg-header-view.hh index dda4de0d..7a51849c 100644 --- a/toys/mug/mu-msg-header-view.hh +++ b/toys/mug/mu-msg-header-view.hh @@ -26,22 +26,26 @@ G_BEGIN_DECLS /* convenience macros */ -#define MU_TYPE_MSG_HEADER_VIEW (mu_msg_header_view_get_type()) -#define MU_MSG_HEADER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_HEADER_VIEW,MuMsgHeaderView)) -#define MU_MSG_HEADER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_HEADER_VIEW,MuMsgHeaderViewClass)) -#define MU_IS_MSG_HEADER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_HEADER_VIEW)) -#define MU_IS_MSG_HEADER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_HEADER_VIEW)) -#define MU_MSG_HEADER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_HEADER_VIEW,MuMsgHeaderViewClass)) +#define MU_TYPE_MSG_HEADER_VIEW (mu_msg_header_view_get_type()) +#define MU_MSG_HEADER_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MU_TYPE_MSG_HEADER_VIEW, MuMsgHeaderView)) +#define MU_MSG_HEADER_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MU_TYPE_MSG_HEADER_VIEW, MuMsgHeaderViewClass)) +#define MU_IS_MSG_HEADER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), MU_TYPE_MSG_HEADER_VIEW)) +#define MU_IS_MSG_HEADER_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), MU_TYPE_MSG_HEADER_VIEW)) +#define MU_MSG_HEADER_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MU_TYPE_MSG_HEADER_VIEW, MuMsgHeaderViewClass)) -typedef struct _MuMsgHeaderView MuMsgHeaderView; -typedef struct _MuMsgHeaderViewClass MuMsgHeaderViewClass; -typedef struct _MuMsgHeaderViewPrivate MuMsgHeaderViewPrivate; +typedef struct _MuMsgHeaderView MuMsgHeaderView; +typedef struct _MuMsgHeaderViewClass MuMsgHeaderViewClass; +typedef struct _MuMsgHeaderViewPrivate MuMsgHeaderViewPrivate; struct _MuMsgHeaderView { GtkBox parent; /* insert public members, if any */ /* private */ - MuMsgHeaderViewPrivate *_priv; + MuMsgHeaderViewPrivate* _priv; }; struct _MuMsgHeaderViewClass { @@ -51,15 +55,14 @@ struct _MuMsgHeaderViewClass { }; /* member functions */ -GType mu_msg_header_view_get_type (void) G_GNUC_CONST; +GType mu_msg_header_view_get_type(void) G_GNUC_CONST; /* parameter-less _new function (constructor) */ /* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mu_msg_header_view_new (void); +GtkWidget* mu_msg_header_view_new(void); struct MuMsg; -void mu_msg_header_view_set_message (MuMsgHeaderView *self, Mu::MuMsg *msg); - +void mu_msg_header_view_set_message(MuMsgHeaderView* self, Mu::MuMsg* msg); G_END_DECLS diff --git a/toys/mug/mu-msg-view.cc b/toys/mug/mu-msg-view.cc index e43496f3..fba6b3f8 100644 --- a/toys/mug/mu-msg-view.cc +++ b/toys/mug/mu-msg-view.cc @@ -31,9 +31,9 @@ using namespace Mu; /* 'private'/'protected' functions */ -static void mu_msg_view_class_init (MuMsgViewClass *klass); -static void mu_msg_view_init (MuMsgView *obj); -static void mu_msg_view_finalize (GObject *obj); +static void mu_msg_view_class_init(MuMsgViewClass* klass); +static void mu_msg_view_init(MuMsgView* obj); +static void mu_msg_view_finalize(GObject* obj); /* list my signals */ enum { @@ -44,202 +44,181 @@ enum { struct _MuMsgViewPrivate { GtkWidget *_headers, *_attach, *_attachexpander, *_body; - Mu::MuMsg *_msg; + Mu::MuMsg* _msg; }; -#define MU_MSG_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MU_TYPE_MSG_VIEW, \ - MuMsgViewPrivate)) +#define MU_MSG_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MU_TYPE_MSG_VIEW, MuMsgViewPrivate)) /* globals */ -static GtkBoxClass *parent_class = NULL; +static GtkBoxClass* parent_class = NULL; /* uncomment the following if you have defined any signals */ /* static guint signals[LAST_SIGNAL] = {0}; */ -G_DEFINE_TYPE (MuMsgView, mu_msg_view, GTK_TYPE_BOX); +G_DEFINE_TYPE(MuMsgView, mu_msg_view, GTK_TYPE_BOX); static void -set_message (MuMsgView *self, Mu::MuMsg *msg) +set_message(MuMsgView* self, Mu::MuMsg* msg) { if (self->_priv->_msg == msg) return; /* nothing to todo */ - if (self->_priv->_msg) { - mu_msg_unref (self->_priv->_msg); + if (self->_priv->_msg) { + mu_msg_unref(self->_priv->_msg); self->_priv->_msg = NULL; } if (msg) - self->_priv->_msg = mu_msg_ref (msg); + self->_priv->_msg = mu_msg_ref(msg); } - static void -mu_msg_view_class_init (MuMsgViewClass *klass) +mu_msg_view_class_init(MuMsgViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass*) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkBoxClass*)g_type_class_peek_parent (klass); + parent_class = (GtkBoxClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mu_msg_view_finalize; - g_type_class_add_private (gobject_class, sizeof(MuMsgViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MuMsgViewPrivate)); /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ + /* signals[MY_SIGNAL_1] = */ + /* g_signal_new ("my_signal_1",....); */ + /* signals[MY_SIGNAL_2] = */ + /* g_signal_new ("my_signal_2",....); */ + /* etc. */ } - static void -on_body_action_requested (GtkWidget *w, const char* action, - MuMsgView *self) +on_body_action_requested(GtkWidget* w, const char* action, MuMsgView* self) { - if (g_strcmp0 (action, "view-source") == 0) { + if (g_strcmp0(action, "view-source") == 0) { if (self->_priv->_msg) - mu_msg_view_set_message_source (self, self->_priv->_msg); + mu_msg_view_set_message_source(self, self->_priv->_msg); - } else if (g_strcmp0 (action, "view-message") == 0) { + } else if (g_strcmp0(action, "view-message") == 0) { if (self->_priv->_msg) - mu_msg_view_set_message (self, self->_priv->_msg); + mu_msg_view_set_message(self, self->_priv->_msg); - } else if (g_strcmp0 (action, "reindex") == 0) - g_warning ("reindex"); + } else if (g_strcmp0(action, "reindex") == 0) + g_warning("reindex"); else - g_warning ("unknown action '%s'", action); + g_warning("unknown action '%s'", action); } static void -on_attach_activated (GtkWidget *w, guint partnum, Mu::MuMsg *msg) +on_attach_activated(GtkWidget* w, guint partnum, Mu::MuMsg* msg) { - gchar *filepath; - GError *err; + gchar* filepath; + GError* err; - err = NULL; - filepath = mu_msg_part_get_cache_path (msg, MU_MSG_OPTION_NONE, partnum, - &err); + err = NULL; + filepath = mu_msg_part_get_cache_path(msg, MU_MSG_OPTION_NONE, partnum, &err); if (!filepath) { - g_warning ("failed to get cache path: %s", - err&&err->message?err->message:"error"); - g_clear_error (&err); + g_warning("failed to get cache path: %s", + err && err->message ? err->message : "error"); + g_clear_error(&err); return; } - if (!mu_msg_part_save (msg, MU_MSG_OPTION_USE_EXISTING, - filepath, partnum, &err)) { - g_warning ("failed to save %s: %s", filepath, - err&&err->message?err->message:"error"); - g_clear_error (&err); + if (!mu_msg_part_save(msg, MU_MSG_OPTION_USE_EXISTING, filepath, partnum, &err)) { + g_warning("failed to save %s: %s", + filepath, + err && err->message ? err->message : "error"); + g_clear_error(&err); return; } else - mu_util_play (filepath, TRUE, FALSE, NULL); + mu_util_play(filepath, TRUE, FALSE, NULL); - g_free (filepath); + g_free(filepath); } - static void -mu_msg_view_init (MuMsgView *self) +mu_msg_view_init(MuMsgView* self) { - gtk_orientable_set_orientation (GTK_ORIENTABLE(self), - GTK_ORIENTATION_VERTICAL); + gtk_orientable_set_orientation(GTK_ORIENTABLE(self), GTK_ORIENTATION_VERTICAL); self->_priv = MU_MSG_VIEW_GET_PRIVATE(self); - self->_priv->_msg = NULL; - self->_priv->_headers = mu_msg_header_view_new (); - self->_priv->_attach = mu_msg_attach_view_new (); - self->_priv->_attachexpander = gtk_expander_new_with_mnemonic - ("_Attachments"); + self->_priv->_msg = NULL; + self->_priv->_headers = mu_msg_header_view_new(); + self->_priv->_attach = mu_msg_attach_view_new(); + self->_priv->_attachexpander = gtk_expander_new_with_mnemonic("_Attachments"); - gtk_container_add (GTK_CONTAINER(self->_priv->_attachexpander), - self->_priv->_attach); - g_signal_connect (self->_priv->_attach, "attach-activated", - G_CALLBACK(on_attach_activated), - self); + gtk_container_add(GTK_CONTAINER(self->_priv->_attachexpander), self->_priv->_attach); + g_signal_connect(self->_priv->_attach, + "attach-activated", + G_CALLBACK(on_attach_activated), + self); - self->_priv->_body = mu_msg_body_view_new (); - g_signal_connect (self->_priv->_body, - "action-requested", - G_CALLBACK(on_body_action_requested), - self); + self->_priv->_body = mu_msg_body_view_new(); + g_signal_connect(self->_priv->_body, + "action-requested", + G_CALLBACK(on_body_action_requested), + self); - gtk_box_pack_start (GTK_BOX(self), self->_priv->_headers, - FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX(self), self->_priv->_attachexpander, - FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX(self), self->_priv->_body, - TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(self), self->_priv->_headers, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(self), self->_priv->_attachexpander, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(self), self->_priv->_body, TRUE, TRUE, 2); } static void -mu_msg_view_finalize (GObject *obj) +mu_msg_view_finalize(GObject* obj) { - set_message (MU_MSG_VIEW (obj), NULL); + set_message(MU_MSG_VIEW(obj), NULL); - G_OBJECT_CLASS(parent_class)->finalize (obj); + G_OBJECT_CLASS(parent_class)->finalize(obj); } GtkWidget* -mu_msg_view_new (void) +mu_msg_view_new(void) { return GTK_WIDGET(g_object_new(MU_TYPE_MSG_VIEW, NULL)); } void -mu_msg_view_set_message (MuMsgView *self, Mu::MuMsg *msg) +mu_msg_view_set_message(MuMsgView* self, Mu::MuMsg* msg) { gint attachnum; - g_return_if_fail (MU_IS_MSG_VIEW(self)); + g_return_if_fail(MU_IS_MSG_VIEW(self)); - set_message (self, msg); + set_message(self, msg); - mu_msg_header_view_set_message (MU_MSG_HEADER_VIEW(self->_priv->_headers), - msg); - attachnum = mu_msg_attach_view_set_message (MU_MSG_ATTACH_VIEW(self->_priv->_attach), - msg); + mu_msg_header_view_set_message(MU_MSG_HEADER_VIEW(self->_priv->_headers), msg); + attachnum = mu_msg_attach_view_set_message(MU_MSG_ATTACH_VIEW(self->_priv->_attach), msg); - mu_msg_body_view_set_message (MU_MSG_BODY_VIEW(self->_priv->_body), - msg); + mu_msg_body_view_set_message(MU_MSG_BODY_VIEW(self->_priv->_body), msg); - gtk_widget_set_visible (self->_priv->_headers, TRUE); - gtk_widget_set_visible (self->_priv->_attachexpander, attachnum > 0); - gtk_widget_set_visible (self->_priv->_body, TRUE); + gtk_widget_set_visible(self->_priv->_headers, TRUE); + gtk_widget_set_visible(self->_priv->_attachexpander, attachnum > 0); + gtk_widget_set_visible(self->_priv->_body, TRUE); } - - void -mu_msg_view_set_message_source (MuMsgView *self, - Mu::MuMsg *msg) +mu_msg_view_set_message_source(MuMsgView* self, Mu::MuMsg* msg) { - g_return_if_fail (MU_IS_MSG_VIEW(self)); + g_return_if_fail(MU_IS_MSG_VIEW(self)); - set_message (self, msg); + set_message(self, msg); - mu_msg_body_view_set_message_source (MU_MSG_BODY_VIEW(self->_priv->_body), - msg); + mu_msg_body_view_set_message_source(MU_MSG_BODY_VIEW(self->_priv->_body), msg); - gtk_widget_set_visible (self->_priv->_headers, FALSE); - gtk_widget_set_visible (self->_priv->_attachexpander, FALSE); - gtk_widget_set_visible (self->_priv->_body, TRUE); + gtk_widget_set_visible(self->_priv->_headers, FALSE); + gtk_widget_set_visible(self->_priv->_attachexpander, FALSE); + gtk_widget_set_visible(self->_priv->_body, TRUE); } - - void -mu_msg_view_set_note (MuMsgView *self, const gchar* html) +mu_msg_view_set_note(MuMsgView* self, const gchar* html) { - g_return_if_fail (MU_IS_MSG_VIEW(self)); + g_return_if_fail(MU_IS_MSG_VIEW(self)); - gtk_widget_set_visible (self->_priv->_headers, FALSE); - gtk_widget_set_visible (self->_priv->_attachexpander, FALSE); - gtk_widget_set_visible (self->_priv->_body, TRUE); + gtk_widget_set_visible(self->_priv->_headers, FALSE); + gtk_widget_set_visible(self->_priv->_attachexpander, FALSE); + gtk_widget_set_visible(self->_priv->_body, TRUE); - mu_msg_body_view_set_note (MU_MSG_BODY_VIEW(self->_priv->_body), - html); + mu_msg_body_view_set_note(MU_MSG_BODY_VIEW(self->_priv->_body), html); } diff --git a/toys/mug/mu-msg-view.hh b/toys/mug/mu-msg-view.hh index f960b3dc..7a6dbfa0 100644 --- a/toys/mug/mu-msg-view.hh +++ b/toys/mug/mu-msg-view.hh @@ -26,21 +26,23 @@ G_BEGIN_DECLS /* convenience macros */ -#define MU_TYPE_MSG_VIEW (mu_msg_view_get_type()) -#define MU_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),MU_TYPE_MSG_VIEW,MuMsgView)) -#define MU_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),MU_TYPE_MSG_VIEW,MuMsgViewClass)) -#define MU_IS_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),MU_TYPE_MSG_VIEW)) -#define MU_IS_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),MU_TYPE_MSG_VIEW)) -#define MU_MSG_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),MU_TYPE_MSG_VIEW,MuMsgViewClass)) +#define MU_TYPE_MSG_VIEW (mu_msg_view_get_type()) +#define MU_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), MU_TYPE_MSG_VIEW, MuMsgView)) +#define MU_MSG_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MU_TYPE_MSG_VIEW, MuMsgViewClass)) +#define MU_IS_MSG_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), MU_TYPE_MSG_VIEW)) +#define MU_IS_MSG_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), MU_TYPE_MSG_VIEW)) +#define MU_MSG_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MU_TYPE_MSG_VIEW, MuMsgViewClass)) -typedef struct _MuMsgView MuMsgView; -typedef struct _MuMsgViewClass MuMsgViewClass; -typedef struct _MuMsgViewPrivate MuMsgViewPrivate; +typedef struct _MuMsgView MuMsgView; +typedef struct _MuMsgViewClass MuMsgViewClass; +typedef struct _MuMsgViewPrivate MuMsgViewPrivate; struct _MuMsgView { GtkBox parent; /* private */ - MuMsgViewPrivate *_priv; + MuMsgViewPrivate* _priv; }; struct _MuMsgViewClass { @@ -49,17 +51,17 @@ struct _MuMsgViewClass { }; /* member functions */ -GType mu_msg_view_get_type (void) G_GNUC_CONST; +GType mu_msg_view_get_type(void) G_GNUC_CONST; /* parameter-less _new function (constructor) */ /* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ -GtkWidget* mu_msg_view_new (void); +GtkWidget* mu_msg_view_new(void); struct MuMsg; -void mu_msg_view_set_message (MuMsgView *self, Mu::MuMsg *msg); -void mu_msg_view_set_note (MuMsgView *self, const gchar* html); -void mu_msg_view_set_message_source (MuMsgView *self, Mu::MuMsg *msg); +void mu_msg_view_set_message(MuMsgView* self, Mu::MuMsg* msg); +void mu_msg_view_set_note(MuMsgView* self, const gchar* html); +void mu_msg_view_set_message_source(MuMsgView* self, Mu::MuMsg* msg); G_END_DECLS diff --git a/toys/mug/mug-msg-list-view.cc b/toys/mug/mug-msg-list-view.cc index 34d2d7a5..0f86b3f8 100644 --- a/toys/mug/mug-msg-list-view.cc +++ b/toys/mug/mug-msg-list-view.cc @@ -25,397 +25,404 @@ using namespace Mu; /* 'private'/'protected' functions */ -static void mug_msg_list_view_finalize (GObject * obj); +static void mug_msg_list_view_finalize(GObject* obj); /* list my signals */ -enum { - MUG_MSG_SELECTED, - MUG_ERROR_OCCURED, - LAST_SIGNAL -}; +enum { MUG_MSG_SELECTED, MUG_ERROR_OCCURED, LAST_SIGNAL }; enum { - MUG_COL_DATESTR, - MUG_COL_MAILDIR, - MUG_COL_FLAGSSTR, - MUG_COL_FROM, - MUG_COL_TO, - MUG_COL_SUBJECT, - MUG_COL_PATH, - MUG_COL_PRIO, - MUG_COL_FLAGS, - MUG_COL_TIME, - MUG_N_COLS + MUG_COL_DATESTR, + MUG_COL_MAILDIR, + MUG_COL_FLAGSSTR, + MUG_COL_FROM, + MUG_COL_TO, + MUG_COL_SUBJECT, + MUG_COL_PATH, + MUG_COL_PRIO, + MUG_COL_FLAGS, + MUG_COL_TIME, + MUG_N_COLS }; typedef struct _MugMsgListViewPrivate MugMsgListViewPrivate; struct _MugMsgListViewPrivate { - GtkTreeStore *_store; - char *_xpath; - char *_query; + GtkTreeStore* _store; + char* _xpath; + char* _query; }; -#define MUG_MSG_LIST_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_MSG_LIST_VIEW, \ - MugMsgListViewPrivate)) +#define MUG_MSG_LIST_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MUG_TYPE_MSG_LIST_VIEW, MugMsgListViewPrivate)) /* globals */ -static GtkTreeViewClass *parent_class = NULL; +static GtkTreeViewClass* parent_class = NULL; /* uncomment the following if you have defined any signals */ -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = {0}; -G_DEFINE_TYPE (MugMsgListView, mug_msg_list_view, GTK_TYPE_TREE_VIEW); +G_DEFINE_TYPE(MugMsgListView, mug_msg_list_view, GTK_TYPE_TREE_VIEW); static void -mug_msg_list_view_class_init (MugMsgListViewClass * klass) +mug_msg_list_view_class_init(MugMsgListViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass *) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkTreeViewClass*)g_type_class_peek_parent (klass); - gobject_class->finalize = mug_msg_list_view_finalize; + parent_class = (GtkTreeViewClass*)g_type_class_peek_parent(klass); + gobject_class->finalize = mug_msg_list_view_finalize; - g_type_class_add_private (gobject_class, - sizeof (MugMsgListViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MugMsgListViewPrivate)); - signals[MUG_MSG_SELECTED] = - g_signal_new ("msg-selected", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MugMsgListViewClass, - msg_selected), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - signals[MUG_ERROR_OCCURED] = - g_signal_new ("error-occured", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MugMsgListViewClass, - error_occured), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); + signals[MUG_MSG_SELECTED] = g_signal_new("msg-selected", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugMsgListViewClass, msg_selected), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals[MUG_ERROR_OCCURED] = + g_signal_new("error-occured", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugMsgListViewClass, error_occured), + NULL, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, + G_TYPE_UINT); } static void -on_cursor_changed (GtkTreeView * tview, MugMsgListView * lst) +on_cursor_changed(GtkTreeView* tview, MugMsgListView* lst) { - GtkTreeSelection *sel; - GtkTreeIter iter; - MugMsgListViewPrivate *priv; + GtkTreeSelection* sel; + GtkTreeIter iter; + MugMsgListViewPrivate* priv; - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE (tview); + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(tview); - sel = gtk_tree_view_get_selection (tview); - if (!sel) - return; /* hmmm */ - if (gtk_tree_selection_get_selected (sel, NULL, &iter)) { - char *path; - gtk_tree_model_get (GTK_TREE_MODEL (priv->_store), &iter, - MUG_COL_PATH, &path, -1); - g_signal_emit (G_OBJECT (lst), - signals[MUG_MSG_SELECTED], 0, path); - g_free (path); - } + sel = gtk_tree_view_get_selection(tview); + if (!sel) + return; /* hmmm */ + if (gtk_tree_selection_get_selected(sel, NULL, &iter)) { + char* path; + gtk_tree_model_get(GTK_TREE_MODEL(priv->_store), &iter, MUG_COL_PATH, &path, -1); + g_signal_emit(G_OBJECT(lst), signals[MUG_MSG_SELECTED], 0, path); + g_free(path); + } } static void -treecell_func (GtkTreeViewColumn * tree_column, GtkCellRenderer * renderer, - GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data) +treecell_func(GtkTreeViewColumn* tree_column, + GtkCellRenderer* renderer, + GtkTreeModel* tree_model, + GtkTreeIter* iter, + gpointer data) { - MuFlags flags; - MuMsgPrio prio; + MuFlags flags; + MuMsgPrio prio; - gtk_tree_model_get (tree_model, iter, - MUG_COL_FLAGS, &flags, MUG_COL_PRIO, &prio, -1); + gtk_tree_model_get(tree_model, iter, MUG_COL_FLAGS, &flags, MUG_COL_PRIO, &prio, -1); - g_object_set (G_OBJECT (renderer), - "weight", (flags & MU_FLAG_NEW) ? 800 : 400, - "weight", (flags & MU_FLAG_SEEN) ? 400 : 800, - "foreground", prio == MU_MSG_PRIO_HIGH ? "red" : NULL, - NULL); + g_object_set(G_OBJECT(renderer), + "weight", + (flags & MU_FLAG_NEW) ? 800 : 400, + "weight", + (flags & MU_FLAG_SEEN) ? 400 : 800, + "foreground", + prio == MU_MSG_PRIO_HIGH ? "red" : NULL, + NULL); } /* sortcolidx == -1 means 'sortcolidx = colidx' */ static void -append_col (GtkTreeView * treeview, const char *label, int colidx, - int sortcolidx, gint maxwidth) +append_col(GtkTreeView* treeview, const char* label, int colidx, int sortcolidx, gint maxwidth) { - GtkTreeViewColumn *col; - GtkCellRenderer *renderer; + GtkTreeViewColumn* col; + GtkCellRenderer* renderer; - renderer = gtk_cell_renderer_text_new (); - g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, - NULL); + renderer = gtk_cell_renderer_text_new(); + g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); - col = gtk_tree_view_column_new_with_attributes (label, renderer, "text", - colidx, NULL); - g_object_set (G_OBJECT (col), "resizable", TRUE, NULL); + col = gtk_tree_view_column_new_with_attributes(label, renderer, "text", colidx, NULL); + g_object_set(G_OBJECT(col), "resizable", TRUE, NULL); - gtk_tree_view_column_set_sort_indicator (col, TRUE); + gtk_tree_view_column_set_sort_indicator(col, TRUE); - if (sortcolidx == -1) - sortcolidx = colidx; - gtk_tree_view_column_set_sort_column_id (col, sortcolidx); - gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED); + if (sortcolidx == -1) + sortcolidx = colidx; + gtk_tree_view_column_set_sort_column_id(col, sortcolidx); + gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - if (maxwidth) { - gtk_tree_view_column_set_fixed_width (col, maxwidth); - gtk_tree_view_column_set_expand (col, FALSE); - } else - gtk_tree_view_column_set_expand (col, TRUE); + if (maxwidth) { + gtk_tree_view_column_set_fixed_width(col, maxwidth); + gtk_tree_view_column_set_expand(col, FALSE); + } else + gtk_tree_view_column_set_expand(col, TRUE); - gtk_tree_view_column_set_cell_data_func (col, renderer, - (GtkTreeCellDataFunc) - treecell_func, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(col, + renderer, + (GtkTreeCellDataFunc)treecell_func, + NULL, + NULL); - gtk_tree_view_append_column (treeview, col); + gtk_tree_view_append_column(treeview, col); - gtk_tree_view_columns_autosize (treeview); - gtk_tree_view_set_fixed_height_mode (treeview, TRUE); + gtk_tree_view_columns_autosize(treeview); + gtk_tree_view_set_fixed_height_mode(treeview, TRUE); } static void -mug_msg_list_view_init (MugMsgListView * obj) +mug_msg_list_view_init(MugMsgListView* obj) { - MugMsgListViewPrivate *priv; - GtkTreeView *tview; + MugMsgListViewPrivate* priv; + GtkTreeView* tview; - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE (obj); + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); - priv->_xpath = priv->_query = NULL; - priv->_store = gtk_tree_store_new (MUG_N_COLS, G_TYPE_STRING, /* date */ - G_TYPE_STRING,/* folder */ - G_TYPE_STRING,/* flagstr */ - G_TYPE_STRING, /* from */ - G_TYPE_STRING,/* to */ - G_TYPE_STRING,/* subject */ - G_TYPE_STRING, /* path */ - G_TYPE_UINT, /* prio */ - G_TYPE_UINT, /* flags */ - G_TYPE_INT); /* timeval */ + priv->_xpath = priv->_query = NULL; + priv->_store = gtk_tree_store_new(MUG_N_COLS, + G_TYPE_STRING, /* date */ + G_TYPE_STRING, /* folder */ + G_TYPE_STRING, /* flagstr */ + G_TYPE_STRING, /* from */ + G_TYPE_STRING, /* to */ + G_TYPE_STRING, /* subject */ + G_TYPE_STRING, /* path */ + G_TYPE_UINT, /* prio */ + G_TYPE_UINT, /* flags */ + G_TYPE_INT); /* timeval */ - tview = GTK_TREE_VIEW (obj); - gtk_tree_view_set_model (tview, GTK_TREE_MODEL (priv->_store)); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (obj), TRUE); - gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (obj), - GTK_TREE_VIEW_GRID_LINES_VERTICAL); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (obj), TRUE); + tview = GTK_TREE_VIEW(obj); + gtk_tree_view_set_model(tview, GTK_TREE_MODEL(priv->_store)); + gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(obj), TRUE); + gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(obj), GTK_TREE_VIEW_GRID_LINES_VERTICAL); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(obj), TRUE); - append_col (tview, "Date", MUG_COL_DATESTR, MUG_COL_TIME, 80); - append_col (tview, "Folder", MUG_COL_MAILDIR, -1, 60); - append_col (tview, "F", MUG_COL_FLAGSSTR, -1, 25); - append_col (tview, "From", MUG_COL_FROM, -1, 0); - append_col (tview, "To", MUG_COL_TO, -1, 0); - append_col (tview, "Subject", MUG_COL_SUBJECT, -1, 0); + append_col(tview, "Date", MUG_COL_DATESTR, MUG_COL_TIME, 80); + append_col(tview, "Folder", MUG_COL_MAILDIR, -1, 60); + append_col(tview, "F", MUG_COL_FLAGSSTR, -1, 25); + append_col(tview, "From", MUG_COL_FROM, -1, 0); + append_col(tview, "To", MUG_COL_TO, -1, 0); + append_col(tview, "Subject", MUG_COL_SUBJECT, -1, 0); - g_signal_connect (G_OBJECT (obj), "cursor-changed", - G_CALLBACK (on_cursor_changed), obj); + g_signal_connect(G_OBJECT(obj), "cursor-changed", G_CALLBACK(on_cursor_changed), obj); } static void -mug_msg_list_view_finalize (GObject * obj) +mug_msg_list_view_finalize(GObject* obj) { - MugMsgListViewPrivate *priv; - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE (obj); + MugMsgListViewPrivate* priv; + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(obj); - if (priv->_store) - g_object_unref (priv->_store); + if (priv->_store) + g_object_unref(priv->_store); - g_free (priv->_xpath); - g_free (priv->_query); + g_free(priv->_xpath); + g_free(priv->_query); - G_OBJECT_CLASS (parent_class)->finalize (obj); + G_OBJECT_CLASS(parent_class)->finalize(obj); } void -mug_msg_list_view_move_first (MugMsgListView * self) +mug_msg_list_view_move_first(MugMsgListView* self) { - GtkTreePath *path; + GtkTreePath* path; - g_return_if_fail (MUG_IS_MSG_LIST_VIEW (self)); + g_return_if_fail(MUG_IS_MSG_LIST_VIEW(self)); - path = gtk_tree_path_new_first (); - gtk_tree_view_set_cursor (GTK_TREE_VIEW (self), path, NULL, FALSE); + path = gtk_tree_path_new_first(); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(self), path, NULL, FALSE); - gtk_tree_path_free (path); + gtk_tree_path_free(path); } static gboolean -msg_list_view_move (MugMsgListView * self, gboolean next) +msg_list_view_move(MugMsgListView* self, gboolean next) { - GtkTreePath *path; + GtkTreePath* path; - gtk_tree_view_get_cursor (GTK_TREE_VIEW (self), &path, NULL); - if (!path) - return FALSE; + gtk_tree_view_get_cursor(GTK_TREE_VIEW(self), &path, NULL); + if (!path) + return FALSE; - if (next) - gtk_tree_path_next (path); - else - gtk_tree_path_prev (path); + if (next) + gtk_tree_path_next(path); + else + gtk_tree_path_prev(path); - gtk_tree_view_set_cursor (GTK_TREE_VIEW (self), path, NULL, FALSE); - gtk_tree_path_free (path); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(self), path, NULL, FALSE); + gtk_tree_path_free(path); - return TRUE; + return TRUE; } gboolean -mug_msg_list_view_move_next (MugMsgListView * self) +mug_msg_list_view_move_next(MugMsgListView* self) { - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW (self), FALSE); + g_return_val_if_fail(MUG_IS_MSG_LIST_VIEW(self), FALSE); - return msg_list_view_move (self, TRUE); + return msg_list_view_move(self, TRUE); } gboolean -mug_msg_list_view_move_prev (MugMsgListView * self) +mug_msg_list_view_move_prev(MugMsgListView* self) { - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW (self), FALSE); + g_return_val_if_fail(MUG_IS_MSG_LIST_VIEW(self), FALSE); - return msg_list_view_move (self, FALSE); + return msg_list_view_move(self, FALSE); } -GtkWidget * -mug_msg_list_view_new (const char *xpath) +GtkWidget* +mug_msg_list_view_new(const char* xpath) { - GtkWidget *w; - MugMsgListViewPrivate *priv; + GtkWidget* w; + MugMsgListViewPrivate* priv; - g_return_val_if_fail (xpath, NULL); + g_return_val_if_fail(xpath, NULL); - w = GTK_WIDGET (g_object_new (MUG_TYPE_MSG_LIST_VIEW, NULL)); + w = GTK_WIDGET(g_object_new(MUG_TYPE_MSG_LIST_VIEW, NULL)); - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE (w); - priv->_xpath = g_strdup (xpath); + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(w); + priv->_xpath = g_strdup(xpath); - return w; + return w; } -static gchar * -empty_or_display_contact (const gchar * str) +static gchar* +empty_or_display_contact(const gchar* str) { - if (!str || *str == '\0') - return g_strdup ("-"); - else - return mu_str_display_contact (str); - + if (!str || *str == '\0') + return g_strdup("-"); + else + return mu_str_display_contact(str); } static Mu::Option -run_query (const char *xpath, const char *expr, MugMsgListView * self) +run_query(const char* xpath, const char* expr, MugMsgListView* self) { - Mu::Store store{xpath}; - Mu::Query query{store}; + Mu::Store store{xpath}; + Mu::Query query{store}; - return query.run(expr, MU_MSG_FIELD_ID_DATE, - Mu::QueryFlags::Descending | - Mu::QueryFlags::SkipUnreadable | - Mu::QueryFlags::SkipDuplicates | - Mu::QueryFlags::IncludeRelated | - Mu::QueryFlags::Threading); + return query.run(expr, + MU_MSG_FIELD_ID_DATE, + Mu::QueryFlags::Descending | Mu::QueryFlags::SkipUnreadable | + Mu::QueryFlags::SkipDuplicates | Mu::QueryFlags::IncludeRelated | + Mu::QueryFlags::Threading); } static void -add_row (GtkTreeStore * store, MuMsg *msg, GtkTreeIter *treeiter) +add_row(GtkTreeStore* store, MuMsg* msg, GtkTreeIter* treeiter) { - const gchar *datestr, *flagstr; - gchar *from, *to; - time_t timeval; + const gchar *datestr, *flagstr; + gchar * from, *to; + time_t timeval; - timeval = mu_msg_get_date (msg); - datestr = timeval == 0 ? "-" : mu_date_display_s (timeval); - from = empty_or_display_contact (mu_msg_get_from (msg)); - to = empty_or_display_contact (mu_msg_get_to (msg)); - flagstr = mu_flags_to_str_s (mu_msg_get_flags (msg), MU_FLAG_TYPE_ANY); + timeval = mu_msg_get_date(msg); + datestr = timeval == 0 ? "-" : mu_date_display_s(timeval); + from = empty_or_display_contact(mu_msg_get_from(msg)); + to = empty_or_display_contact(mu_msg_get_to(msg)); + flagstr = mu_flags_to_str_s(mu_msg_get_flags(msg), MU_FLAG_TYPE_ANY); - /* if (0) { */ - /* GtkTreeIter myiter; */ - /* if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(store), */ - /* &myiter, path)) */ - /* g_warning ("%s: cannot get iter for %s", - * __func__, path); */ - /* } */ + /* if (0) { */ + /* GtkTreeIter myiter; */ + /* if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(store), */ + /* &myiter, path)) */ + /* g_warning ("%s: cannot get iter for %s", + * __func__, path); */ + /* } */ - gtk_tree_store_set (store, treeiter, - MUG_COL_DATESTR, datestr, - MUG_COL_MAILDIR, mu_msg_get_maildir (msg), - MUG_COL_FLAGSSTR, flagstr, - MUG_COL_FROM, from, - MUG_COL_TO, to, - MUG_COL_SUBJECT, mu_msg_get_subject (msg), - MUG_COL_PATH, mu_msg_get_path (msg), - MUG_COL_PRIO, mu_msg_get_prio (msg), - MUG_COL_FLAGS, mu_msg_get_flags (msg), - MUG_COL_TIME, timeval, -1); - g_free (from); - g_free (to); + gtk_tree_store_set(store, + treeiter, + MUG_COL_DATESTR, + datestr, + MUG_COL_MAILDIR, + mu_msg_get_maildir(msg), + MUG_COL_FLAGSSTR, + flagstr, + MUG_COL_FROM, + from, + MUG_COL_TO, + to, + MUG_COL_SUBJECT, + mu_msg_get_subject(msg), + MUG_COL_PATH, + mu_msg_get_path(msg), + MUG_COL_PRIO, + mu_msg_get_prio(msg), + MUG_COL_FLAGS, + mu_msg_get_flags(msg), + MUG_COL_TIME, + timeval, + -1); + g_free(from); + g_free(to); } static int -update_model (GtkTreeStore *store, const char *xpath, const char *query, - MugMsgListView *self) +update_model(GtkTreeStore* store, const char* xpath, const char* query, MugMsgListView* self) { - const auto res{run_query (xpath, query, self)}; - if (!res) { - g_warning ("error: running query failed"); - return -1; - } + const auto res{run_query(xpath, query, self)}; + if (!res) { + g_warning("error: running query failed"); + return -1; + } - auto count{0}; + auto count{0}; - std::string prev_thread_path; - for (auto&& it: *res) { - GtkTreeIter treeiter, prev_treeiter; + std::string prev_thread_path; + for (auto&& it : *res) { + GtkTreeIter treeiter, prev_treeiter; - const auto thread_path{it.query_match().thread_path}; + const auto thread_path{it.query_match().thread_path}; - if (prev_thread_path.find(thread_path) == 0) - gtk_tree_store_append (store, &treeiter, &prev_treeiter); - else - gtk_tree_store_append (store, &treeiter, NULL); + if (prev_thread_path.find(thread_path) == 0) + gtk_tree_store_append(store, &treeiter, &prev_treeiter); + else + gtk_tree_store_append(store, &treeiter, NULL); - /* don't unref msg */ - add_row (store, it.floating_msg(), &treeiter); + /* don't unref msg */ + add_row(store, it.floating_msg(), &treeiter); - //prev_ti = ti; - prev_treeiter = treeiter; - prev_thread_path = thread_path; - ++count; - } + // prev_ti = ti; + prev_treeiter = treeiter; + prev_thread_path = thread_path; + ++count; + } - return count; + return count; } int -mug_msg_list_view_query (MugMsgListView * self, const char *query) +mug_msg_list_view_query(MugMsgListView* self, const char* query) { - MugMsgListViewPrivate *priv; - gboolean rv; + MugMsgListViewPrivate* priv; + gboolean rv; - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW (self), FALSE); + g_return_val_if_fail(MUG_IS_MSG_LIST_VIEW(self), FALSE); - priv = MUG_MSG_LIST_VIEW_GET_PRIVATE (self); - gtk_tree_store_clear (priv->_store); + priv = MUG_MSG_LIST_VIEW_GET_PRIVATE(self); + gtk_tree_store_clear(priv->_store); - g_free (priv->_query); - priv->_query = query ? g_strdup (query) : NULL; + g_free(priv->_query); + priv->_query = query ? g_strdup(query) : NULL; - if (!query) - return TRUE; + if (!query) + return TRUE; - rv = update_model (priv->_store, priv->_xpath, query, self); + rv = update_model(priv->_store, priv->_xpath, query, self); - gtk_tree_view_expand_all (GTK_TREE_VIEW(self)); + gtk_tree_view_expand_all(GTK_TREE_VIEW(self)); - return rv; + return rv; } -const gchar * -mug_msg_list_view_get_query (MugMsgListView * self) +const gchar* +mug_msg_list_view_get_query(MugMsgListView* self) { - g_return_val_if_fail (MUG_IS_MSG_LIST_VIEW (self), NULL); + g_return_val_if_fail(MUG_IS_MSG_LIST_VIEW(self), NULL); - return MUG_MSG_LIST_VIEW_GET_PRIVATE (self)->_query; + return MUG_MSG_LIST_VIEW_GET_PRIVATE(self)->_query; } diff --git a/toys/mug/mug-msg-view.cc b/toys/mug/mug-msg-view.cc index 449ffe8e..1bb33796 100644 --- a/toys/mug/mug-msg-view.cc +++ b/toys/mug/mug-msg-view.cc @@ -27,9 +27,9 @@ using namespace Mu; /* 'private'/'protected' functions */ -static void mug_msg_view_class_init (MugMsgViewClass * klass); -static void mug_msg_view_init (MugMsgView * obj); -static void mug_msg_view_finalize (GObject * obj); +static void mug_msg_view_class_init(MugMsgViewClass* klass); +static void mug_msg_view_init(MugMsgView* obj); +static void mug_msg_view_finalize(GObject* obj); /* list my signals */ enum { @@ -38,115 +38,111 @@ enum { LAST_SIGNAL }; - typedef struct _MugMsgViewPrivate MugMsgViewPrivate; struct _MugMsgViewPrivate { - GtkWidget *_view; + GtkWidget* _view; }; -#define MUG_MSG_VIEW_GET_PRIVATE(o)(G_TYPE_INSTANCE_GET_PRIVATE((o),MUG_TYPE_MSG_VIEW, MugMsgViewPrivate)) +#define MUG_MSG_VIEW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MUG_TYPE_MSG_VIEW, MugMsgViewPrivate)) /* globals */ -static GtkBoxClass *parent_class = NULL; -G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_BOX); +static GtkBoxClass* parent_class = NULL; +G_DEFINE_TYPE(MugMsgView, mug_msg_view, GTK_TYPE_BOX); /* uncomment the following if you have defined any signals */ /* static guint signals[LAST_SIGNAL] = {0}; */ static void -mug_msg_view_class_init (MugMsgViewClass * klass) +mug_msg_view_class_init(MugMsgViewClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass *) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkBoxClass*)g_type_class_peek_parent (klass); + parent_class = (GtkBoxClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mug_msg_view_finalize; - g_type_class_add_private (gobject_class, sizeof (MugMsgViewPrivate)); + g_type_class_add_private(gobject_class, sizeof(MugMsgViewPrivate)); /* signal definitions go here, e.g.: */ -/* signals[MY_SIGNAL_1] = */ -/* g_signal_new ("my_signal_1",....); */ -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ + /* signals[MY_SIGNAL_1] = */ + /* g_signal_new ("my_signal_1",....); */ + /* signals[MY_SIGNAL_2] = */ + /* g_signal_new ("my_signal_2",....); */ + /* etc. */ } static void -mug_msg_view_init (MugMsgView * obj) +mug_msg_view_init(MugMsgView* obj) { - MugMsgViewPrivate *priv; - GtkWidget *scrolled; + MugMsgViewPrivate* priv; + GtkWidget* scrolled; - priv = MUG_MSG_VIEW_GET_PRIVATE (obj); + priv = MUG_MSG_VIEW_GET_PRIVATE(obj); - priv->_view = mu_msg_view_new (); + priv->_view = mu_msg_view_new(); - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (scrolled), priv->_view); + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolled), priv->_view); - gtk_box_pack_start (GTK_BOX (obj), scrolled, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(obj), scrolled, TRUE, TRUE, 0); } static void -mug_msg_view_finalize (GObject * obj) +mug_msg_view_finalize(GObject* obj) { -/* free/unref instance resources here */ - G_OBJECT_CLASS (parent_class)->finalize (obj); + /* free/unref instance resources here */ + G_OBJECT_CLASS(parent_class)->finalize(obj); } -GtkWidget * -mug_msg_view_new (void) +GtkWidget* +mug_msg_view_new(void) { - return GTK_WIDGET (g_object_new (MUG_TYPE_MSG_VIEW, NULL)); + return GTK_WIDGET(g_object_new(MUG_TYPE_MSG_VIEW, NULL)); } - - gboolean -mug_msg_view_set_msg (MugMsgView * self, const char *msgpath) +mug_msg_view_set_msg(MugMsgView* self, const char* msgpath) { - MugMsgViewPrivate *priv; - g_return_val_if_fail (MUG_IS_MSG_VIEW (self), FALSE); + MugMsgViewPrivate* priv; + g_return_val_if_fail(MUG_IS_MSG_VIEW(self), FALSE); - priv = MUG_MSG_VIEW_GET_PRIVATE (self); + priv = MUG_MSG_VIEW_GET_PRIVATE(self); if (!msgpath) - mu_msg_view_set_message (MU_MSG_VIEW(priv->_view), NULL); + mu_msg_view_set_message(MU_MSG_VIEW(priv->_view), NULL); else { - Mu::MuMsg *msg; + Mu::MuMsg* msg; - if (access (msgpath, R_OK) == 0) { - msg = mu_msg_new_from_file (msgpath, NULL, NULL); - mu_msg_view_set_message (MU_MSG_VIEW(priv->_view), msg); + if (access(msgpath, R_OK) == 0) { + msg = mu_msg_new_from_file(msgpath, NULL, NULL); + mu_msg_view_set_message(MU_MSG_VIEW(priv->_view), msg); if (msg) - mu_msg_unref (msg); + mu_msg_unref(msg); } else { - gchar *note; - note = g_strdup_printf ( - "

Note


" - "

Message %s does not seem to be present " - "on the file system." - "

Maybe you need to run mu index?", - msgpath); - mu_msg_view_set_note (MU_MSG_VIEW (priv->_view), note); - g_free (note); + gchar* note; + note = g_strdup_printf("

Note


" + "

Message %s does not seem to be present " + "on the file system." + "

Maybe you need to run mu index?", + msgpath); + mu_msg_view_set_note(MU_MSG_VIEW(priv->_view), note); + g_free(note); } } return TRUE; } - void -mug_msg_view_set_note (MugMsgView * self, const char* html) +mug_msg_view_set_note(MugMsgView* self, const char* html) { - MugMsgViewPrivate *priv; - g_return_if_fail (MUG_IS_MSG_VIEW (self)); + MugMsgViewPrivate* priv; + g_return_if_fail(MUG_IS_MSG_VIEW(self)); - priv = MUG_MSG_VIEW_GET_PRIVATE (self); + priv = MUG_MSG_VIEW_GET_PRIVATE(self); - mu_msg_view_set_note (MU_MSG_VIEW (priv->_view), html); + mu_msg_view_set_note(MU_MSG_VIEW(priv->_view), html); } diff --git a/toys/mug/mug-shortcuts.cc b/toys/mug/mug-shortcuts.cc index ed964f3e..ba494eec 100644 --- a/toys/mug/mug-shortcuts.cc +++ b/toys/mug/mug-shortcuts.cc @@ -23,9 +23,9 @@ /* include other impl specific header files */ /* 'private'/'protected' functions */ -static void mug_shortcuts_class_init (MugShortcutsClass * klass); -static void mug_shortcuts_init (MugShortcuts * obj); -static void mug_shortcuts_finalize (GObject * obj); +static void mug_shortcuts_class_init(MugShortcutsClass* klass); +static void mug_shortcuts_init(MugShortcuts* obj); +static void mug_shortcuts_finalize(GObject* obj); #define MUG_SHORTCUT_BOOKMARK "bookmark" @@ -38,115 +38,110 @@ enum { }; struct _MugShortcutsPrivate { - GtkWidget *_bbox; - + GtkWidget* _bbox; }; -#define MUG_SHORTCUTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ - MUG_TYPE_SHORTCUTS, \ - MugShortcutsPrivate)) +#define MUG_SHORTCUTS_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), MUG_TYPE_SHORTCUTS, MugShortcutsPrivate)) /* globals */ -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = {0}; - -static GtkBoxClass *parent_class = NULL; -G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_BOX); +static GtkBoxClass* parent_class = NULL; +G_DEFINE_TYPE(MugShortcuts, mug_shortcuts, GTK_TYPE_BOX); static void -mug_shortcuts_class_init (MugShortcutsClass * klass) +mug_shortcuts_class_init(MugShortcutsClass* klass) { - GObjectClass *gobject_class; - gobject_class = (GObjectClass *) klass; + GObjectClass* gobject_class; + gobject_class = (GObjectClass*)klass; - parent_class = (GtkBoxClass*)g_type_class_peek_parent (klass); + parent_class = (GtkBoxClass*)g_type_class_peek_parent(klass); gobject_class->finalize = mug_shortcuts_finalize; - g_type_class_add_private (gobject_class, sizeof (MugShortcutsPrivate)); + g_type_class_add_private(gobject_class, sizeof(MugShortcutsPrivate)); /* signal definitions go here, e.g.: */ - signals[SHORTCUT_CLICKED] = - g_signal_new ("clicked", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MugShortcutsClass, clicked), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + signals[SHORTCUT_CLICKED] = g_signal_new("clicked", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(MugShortcutsClass, clicked), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); -/* signals[MY_SIGNAL_2] = */ -/* g_signal_new ("my_signal_2",....); */ -/* etc. */ + /* signals[MY_SIGNAL_2] = */ + /* g_signal_new ("my_signal_2",....); */ + /* etc. */ } static void -mug_shortcuts_init (MugShortcuts * obj) +mug_shortcuts_init(MugShortcuts* obj) { - obj->_priv = MUG_SHORTCUTS_GET_PRIVATE (obj); - obj->_priv->_bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL); + obj->_priv = MUG_SHORTCUTS_GET_PRIVATE(obj); + obj->_priv->_bbox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); - gtk_button_box_set_layout (GTK_BUTTON_BOX (obj->_priv->_bbox), - GTK_BUTTONBOX_START); - gtk_box_pack_start (GTK_BOX (obj), obj->_priv->_bbox, TRUE, TRUE, 0); + gtk_button_box_set_layout(GTK_BUTTON_BOX(obj->_priv->_bbox), GTK_BUTTONBOX_START); + gtk_box_pack_start(GTK_BOX(obj), obj->_priv->_bbox, TRUE, TRUE, 0); } static void -mug_shortcuts_finalize (GObject * obj) +mug_shortcuts_finalize(GObject* obj) { -/* free/unref instance resources here */ - G_OBJECT_CLASS (parent_class)->finalize (obj); + /* free/unref instance resources here */ + G_OBJECT_CLASS(parent_class)->finalize(obj); } static void -on_button_clicked (GtkWidget * button, MugShortcuts * self) +on_button_clicked(GtkWidget* button, MugShortcuts* self) { - g_signal_emit (G_OBJECT (self), - signals[SHORTCUT_CLICKED], 0, - (const gchar *)g_object_get_data (G_OBJECT (button), - MUG_SHORTCUT_BOOKMARK)); + g_signal_emit(G_OBJECT(self), + signals[SHORTCUT_CLICKED], + 0, + (const gchar*)g_object_get_data(G_OBJECT(button), MUG_SHORTCUT_BOOKMARK)); } static void -each_bookmark (const char *key, const char *val, MugShortcuts * self) +each_bookmark(const char* key, const char* val, MugShortcuts* self) { - GtkWidget *button; + GtkWidget* button; - button = gtk_button_new_with_label (key); - g_object_set_data_full (G_OBJECT (button), MUG_SHORTCUT_BOOKMARK, - g_strdup (val), g_free); - g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (on_button_clicked), self); + button = gtk_button_new_with_label(key); + g_object_set_data_full(G_OBJECT(button), MUG_SHORTCUT_BOOKMARK, g_strdup(val), g_free); + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), self); - gtk_container_add (GTK_CONTAINER (self->_priv->_bbox), button); + gtk_container_add(GTK_CONTAINER(self->_priv->_bbox), button); } static gboolean -init_shortcuts (MugShortcuts * self, const char *bmpath) +init_shortcuts(MugShortcuts* self, const char* bmpath) { - MuBookmarks *bookmarks; + MuBookmarks* bookmarks; - bookmarks = mu_bookmarks_new (bmpath); + bookmarks = mu_bookmarks_new(bmpath); if (!bookmarks) return TRUE; - mu_bookmarks_foreach (bookmarks, (MuBookmarksForeachFunc) each_bookmark, - self); + mu_bookmarks_foreach(bookmarks, (MuBookmarksForeachFunc)each_bookmark, self); - mu_bookmarks_destroy (bookmarks); + mu_bookmarks_destroy(bookmarks); return TRUE; } -GtkWidget * -mug_shortcuts_new (const char *bmpath) +GtkWidget* +mug_shortcuts_new(const char* bmpath) { - MugShortcuts *self; + MugShortcuts* self; - self = MUG_SHORTCUTS (g_object_new (MUG_TYPE_SHORTCUTS, NULL)); - if (!init_shortcuts (self, bmpath)) { - g_object_unref (self); + self = MUG_SHORTCUTS(g_object_new(MUG_TYPE_SHORTCUTS, NULL)); + if (!init_shortcuts(self, bmpath)) { + g_object_unref(self); return NULL; } - return GTK_WIDGET (self); + return GTK_WIDGET(self); } /* following: other function implementations */ diff --git a/toys/mug/mug.cc b/toys/mug/mug.cc index 5833ee4a..a90cddae 100644 --- a/toys/mug/mug.cc +++ b/toys/mug/mug.cc @@ -21,7 +21,7 @@ #include #include -#include /* for memset */ +#include /* for memset */ #include #include @@ -33,32 +33,33 @@ #include "mug-shortcuts.h" struct _MugData { - GtkWidget *win; - GtkWidget *statusbar; - GtkWidget *mlist; - GtkWidget *toolbar; - GtkWidget *msgview; - GtkWidget *querybar; - GtkWidget *shortcuts; - gchar *muhome; + GtkWidget* win; + GtkWidget* statusbar; + GtkWidget* mlist; + GtkWidget* toolbar; + GtkWidget* msgview; + GtkWidget* querybar; + GtkWidget* shortcuts; + gchar* muhome; }; typedef struct _MugData MugData; - static void -about_mug (MugData * mugdata) +about_mug(MugData* mugdata) { - GtkWidget *about; - about = gtk_message_dialog_new - (GTK_WINDOW (mugdata->win), GTK_DIALOG_MODAL, - GTK_MESSAGE_INFO, GTK_BUTTONS_OK, - "Mug version %s\n" - "A graphical frontend to the 'mu' e-mail search engine\n\n" - "(c) 2010-2013 Dirk-Jan C. Binnema\n" - "Released under the terms of the GPLv3+", VERSION); + GtkWidget* about; + about = gtk_message_dialog_new(GTK_WINDOW(mugdata->win), + GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "Mug version %s\n" + "A graphical frontend to the 'mu' e-mail search engine\n\n" + "(c) 2010-2013 Dirk-Jan C. Binnema\n" + "Released under the terms of the GPLv3+", + VERSION); - gtk_dialog_run (GTK_DIALOG (about)); - gtk_widget_destroy (about); + gtk_dialog_run(GTK_DIALOG(about)); + gtk_widget_destroy(about); } enum _ToolAction { @@ -67,353 +68,334 @@ enum _ToolAction { ACTION_REINDEX, ACTION_DO_QUIT, ACTION_ABOUT, - ACTION_SEPARATOR /* pseudo action */ + ACTION_SEPARATOR /* pseudo action */ }; typedef enum _ToolAction ToolAction; static void -on_tool_button_clicked (GtkToolButton * btn, MugData * mugdata) +on_tool_button_clicked(GtkToolButton* btn, MugData* mugdata) { ToolAction action; - action = (ToolAction) - GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (btn), "action")); + action = (ToolAction)GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(btn), "action")); switch (action) { - - case ACTION_DO_QUIT: - gtk_main_quit (); - break; - case ACTION_NEXT_MSG: - mug_msg_list_view_move_next (MUG_MSG_LIST_VIEW - (mugdata->mlist)); - break; - case ACTION_PREV_MSG: - mug_msg_list_view_move_prev (MUG_MSG_LIST_VIEW - (mugdata->mlist)); - break; - case ACTION_ABOUT: - about_mug (mugdata); - break; - default: - g_print ("%u\n", action); + case ACTION_DO_QUIT: gtk_main_quit(); break; + case ACTION_NEXT_MSG: mug_msg_list_view_move_next(MUG_MSG_LIST_VIEW(mugdata->mlist)); break; + case ACTION_PREV_MSG: mug_msg_list_view_move_prev(MUG_MSG_LIST_VIEW(mugdata->mlist)); break; + case ACTION_ABOUT: about_mug(mugdata); break; + default: g_print("%u\n", action); } } - - static GtkToolItem* -tool_button (const char *name) +tool_button(const char* name) { - GtkWidget *icon; + GtkWidget* icon; - icon = gtk_image_new_from_icon_name - (name, GTK_ICON_SIZE_SMALL_TOOLBAR); + icon = gtk_image_new_from_icon_name(name, GTK_ICON_SIZE_SMALL_TOOLBAR); - return gtk_menu_tool_button_new (icon, NULL); + return gtk_menu_tool_button_new(icon, NULL); } - static GtkToolItem* -get_connected_tool_button (const char* stock_id, ToolAction action, - MugData *mugdata) +get_connected_tool_button(const char* stock_id, ToolAction action, MugData* mugdata) { - GtkToolItem *btn; + GtkToolItem* btn; - btn = tool_button (stock_id); - g_object_set_data (G_OBJECT (btn), "action", - GUINT_TO_POINTER (action)); - g_signal_connect (G_OBJECT (btn), "clicked", - G_CALLBACK (on_tool_button_clicked), - mugdata); + btn = tool_button(stock_id); + g_object_set_data(G_OBJECT(btn), "action", GUINT_TO_POINTER(action)); + g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(on_tool_button_clicked), mugdata); return btn; } -static GtkWidget * -mug_toolbar (MugData * mugdata) +static GtkWidget* +mug_toolbar(MugData* mugdata) { - GtkWidget *toolbar; - int i; + GtkWidget* toolbar; + int i; struct { - const char *stock_id; - ToolAction action; - } tools[] = { - {"go-up", ACTION_PREV_MSG}, - {"go-down", ACTION_NEXT_MSG}, - {NULL, ACTION_SEPARATOR}, - {"view-refresh", ACTION_REINDEX}, - {NULL, ACTION_SEPARATOR}, - {"help-about", ACTION_ABOUT}, - {NULL, ACTION_SEPARATOR}, - {"application-exit", ACTION_DO_QUIT}}; + const char* stock_id; + ToolAction action; + } tools[] = {{"go-up", ACTION_PREV_MSG}, + {"go-down", ACTION_NEXT_MSG}, + {NULL, ACTION_SEPARATOR}, + {"view-refresh", ACTION_REINDEX}, + {NULL, ACTION_SEPARATOR}, + {"help-about", ACTION_ABOUT}, + {NULL, ACTION_SEPARATOR}, + {"application-exit", ACTION_DO_QUIT}}; - toolbar = gtk_toolbar_new (); - for (i = 0; i != G_N_ELEMENTS (tools); ++i) { + toolbar = gtk_toolbar_new(); + for (i = 0; i != G_N_ELEMENTS(tools); ++i) { if (tools[i].action == ACTION_SEPARATOR) { /* separator? */ - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - gtk_separator_tool_item_new (), i); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), gtk_separator_tool_item_new(), i); continue; } else /* nope: a real item */ - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - get_connected_tool_button - (tools[i].stock_id, tools[i].action, - mugdata), i); + gtk_toolbar_insert( + GTK_TOOLBAR(toolbar), + get_connected_tool_button(tools[i].stock_id, tools[i].action, mugdata), + i); } return toolbar; } static void -on_shortcut_clicked (GtkWidget * w, const gchar * query, MugData * mdata) +on_shortcut_clicked(GtkWidget* w, const gchar* query, MugData* mdata) { - mug_query_bar_set_query (MUG_QUERY_BAR (mdata->querybar), query, TRUE); + mug_query_bar_set_query(MUG_QUERY_BAR(mdata->querybar), query, TRUE); } -static GtkWidget * -mug_shortcuts_bar (MugData * data) +static GtkWidget* +mug_shortcuts_bar(MugData* data) { - data->shortcuts = mug_shortcuts_new - (mu_runtime_path(MU_RUNTIME_PATH_BOOKMARKS)); + data->shortcuts = mug_shortcuts_new(mu_runtime_path(MU_RUNTIME_PATH_BOOKMARKS)); - g_signal_connect (G_OBJECT (data->shortcuts), "clicked", - G_CALLBACK (on_shortcut_clicked), data); + g_signal_connect(G_OBJECT(data->shortcuts), + "clicked", + G_CALLBACK(on_shortcut_clicked), + data); return data->shortcuts; } -static GtkWidget * -mug_statusbar (void) +static GtkWidget* +mug_statusbar(void) { - GtkWidget *statusbar; + GtkWidget* statusbar; - statusbar = gtk_statusbar_new (); + statusbar = gtk_statusbar_new(); return statusbar; } static void -on_query_changed (MugQueryBar * bar, const char *query, MugData * mugdata) +on_query_changed(MugQueryBar* bar, const char* query, MugData* mugdata) { int count; /* clear the old message */ - mug_msg_view_set_msg (MUG_MSG_VIEW (mugdata->msgview), NULL); + mug_msg_view_set_msg(MUG_MSG_VIEW(mugdata->msgview), NULL); - count = mug_msg_list_view_query (MUG_MSG_LIST_VIEW (mugdata->mlist), - query); + count = mug_msg_list_view_query(MUG_MSG_LIST_VIEW(mugdata->mlist), query); if (count >= 0) { - gchar *msg = - g_strdup_printf ("%d message%s found matching '%s'", - count, - count > 1 ? "s" : "", - mug_msg_list_view_get_query - (MUG_MSG_LIST_VIEW (mugdata->mlist))); - gtk_statusbar_push (GTK_STATUSBAR (mugdata->statusbar), 0, msg); - g_free (msg); + gchar* msg = + g_strdup_printf("%d message%s found matching '%s'", + count, + count > 1 ? "s" : "", + mug_msg_list_view_get_query(MUG_MSG_LIST_VIEW(mugdata->mlist))); + gtk_statusbar_push(GTK_STATUSBAR(mugdata->statusbar), 0, msg); + g_free(msg); - mug_msg_list_view_move_first (MUG_MSG_LIST_VIEW - (mugdata->mlist)); - gtk_widget_grab_focus (GTK_WIDGET (mugdata->mlist)); + mug_msg_list_view_move_first(MUG_MSG_LIST_VIEW(mugdata->mlist)); + gtk_widget_grab_focus(GTK_WIDGET(mugdata->mlist)); } - if (count == 0) /* nothing found */ - mug_query_bar_grab_focus (MUG_QUERY_BAR (bar)); + if (count == 0) /* nothing found */ + mug_query_bar_grab_focus(MUG_QUERY_BAR(bar)); } static void -on_msg_selected (MugMsgListView * mlist, const char *mpath, MugData * mugdata) +on_msg_selected(MugMsgListView* mlist, const char* mpath, MugData* mugdata) { - mug_msg_view_set_msg (MUG_MSG_VIEW (mugdata->msgview), mpath); + mug_msg_view_set_msg(MUG_MSG_VIEW(mugdata->msgview), mpath); } static void -on_list_view_error (MugMsgListView * mlist, MugError err, MugData * mugdata) +on_list_view_error(MugMsgListView* mlist, MugError err, MugData* mugdata) { - GtkWidget *errdialog; - const char *msg; + GtkWidget* errdialog; + const char* msg; switch (err) { case MUG_ERROR_XAPIAN_NOT_UPTODATE: msg = "The Xapian Database has the wrong version\n" - "Please run 'mu index --rebuild'"; + "Please run 'mu index --rebuild'"; break; case MUG_ERROR_XAPIAN_DIR: msg = "Cannot find the Xapian database dir\n" - "Please restart mug with --muhome=... pointing\n" - "to your mu home directory"; - break; - case MUG_ERROR_QUERY: - msg = "Error in query"; - break; - default: - msg = "Some error occurred"; + "Please restart mug with --muhome=... pointing\n" + "to your mu home directory"; break; + case MUG_ERROR_QUERY: msg = "Error in query"; break; + default: msg = "Some error occurred"; break; } - errdialog = gtk_message_dialog_new - (GTK_WINDOW (mugdata->win), GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg); + errdialog = gtk_message_dialog_new(GTK_WINDOW(mugdata->win), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", + msg); - gtk_dialog_run (GTK_DIALOG (errdialog)); - gtk_widget_destroy (errdialog); + gtk_dialog_run(GTK_DIALOG(errdialog)); + gtk_widget_destroy(errdialog); if (err == MUG_ERROR_QUERY) - mug_query_bar_grab_focus (MUG_QUERY_BAR (mugdata->querybar)); + mug_query_bar_grab_focus(MUG_QUERY_BAR(mugdata->querybar)); } -static GtkWidget * -mug_querybar (void) +static GtkWidget* +mug_querybar(void) { - GtkWidget *querybar; + GtkWidget* querybar; - querybar = mug_query_bar_new (); + querybar = mug_query_bar_new(); return querybar; } -static GtkWidget * -mug_query_area (MugData * mugdata) +static GtkWidget* +mug_query_area(MugData* mugdata) { GtkWidget *queryarea, *paned, *scrolled; - queryarea = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); - paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL); + queryarea = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2); + paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); - mugdata->mlist = mug_msg_list_view_new - (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)); - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); + mugdata->mlist = mug_msg_list_view_new(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)); + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (scrolled), mugdata->mlist); - gtk_paned_add1 (GTK_PANED (paned), scrolled); + gtk_container_add(GTK_CONTAINER(scrolled), mugdata->mlist); + gtk_paned_add1(GTK_PANED(paned), scrolled); - mugdata->msgview = mug_msg_view_new (); - mug_msg_view_set_note (MUG_MSG_VIEW(mugdata->msgview), - "

Welcome to mug!


" - "mug is an experimental UI for mu, which will " - "slowly evolve into something useful.

Enjoy the ride."); - g_signal_connect (G_OBJECT (mugdata->mlist), "msg-selected", - G_CALLBACK (on_msg_selected), mugdata); - g_signal_connect (G_OBJECT (mugdata->mlist), "error-occured", - G_CALLBACK (on_list_view_error), mugdata); - gtk_paned_add2 (GTK_PANED (paned), mugdata->msgview); + mugdata->msgview = mug_msg_view_new(); + mug_msg_view_set_note(MUG_MSG_VIEW(mugdata->msgview), + "

Welcome to mug!


" + "mug is an experimental UI for mu, which will " + "slowly evolve into something useful.

Enjoy the ride."); + g_signal_connect(G_OBJECT(mugdata->mlist), + "msg-selected", + G_CALLBACK(on_msg_selected), + mugdata); + g_signal_connect(G_OBJECT(mugdata->mlist), + "error-occured", + G_CALLBACK(on_list_view_error), + mugdata); + gtk_paned_add2(GTK_PANED(paned), mugdata->msgview); - mugdata->querybar = mug_querybar (); - g_signal_connect (G_OBJECT (mugdata->querybar), "query-changed", - G_CALLBACK (on_query_changed), mugdata); + mugdata->querybar = mug_querybar(); + g_signal_connect(G_OBJECT(mugdata->querybar), + "query-changed", + G_CALLBACK(on_query_changed), + mugdata); - gtk_box_pack_start (GTK_BOX (queryarea), - mugdata->querybar, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (queryarea), paned, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(queryarea), mugdata->querybar, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(queryarea), paned, TRUE, TRUE, 2); - gtk_widget_show_all (queryarea); + gtk_widget_show_all(queryarea); return queryarea; } -static GtkWidget * -mug_main_area (MugData * mugdata) +static GtkWidget* +mug_main_area(MugData* mugdata) { GtkWidget *mainarea, *w; - mainarea = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + mainarea = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); - w = mug_shortcuts_bar (mugdata); - gtk_box_pack_start (GTK_BOX (mainarea), w, FALSE, FALSE, 0); - gtk_widget_show (w); + w = mug_shortcuts_bar(mugdata); + gtk_box_pack_start(GTK_BOX(mainarea), w, FALSE, FALSE, 0); + gtk_widget_show(w); - w = mug_query_area (mugdata); - gtk_box_pack_start (GTK_BOX (mainarea), w, TRUE, TRUE, 0); - gtk_widget_show (w); + w = mug_query_area(mugdata); + gtk_box_pack_start(GTK_BOX(mainarea), w, TRUE, TRUE, 0); + gtk_widget_show(w); return mainarea; } static GtkWidget* -mug_shell (MugData *mugdata) +mug_shell(MugData* mugdata) { - GtkWidget *vbox; + GtkWidget* vbox; - mugdata->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (mugdata->win), "Mug Mail Search"); + mugdata->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(mugdata->win), "Mug Mail Search"); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2); - mugdata->toolbar = mug_toolbar (mugdata); - gtk_box_pack_start (GTK_BOX (vbox), mugdata->toolbar, FALSE, FALSE, 2); - gtk_box_pack_start (GTK_BOX (vbox), mug_main_area (mugdata), TRUE, - TRUE, 2); + mugdata->toolbar = mug_toolbar(mugdata); + gtk_box_pack_start(GTK_BOX(vbox), mugdata->toolbar, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), mug_main_area(mugdata), TRUE, TRUE, 2); - mugdata->statusbar = mug_statusbar (); - gtk_box_pack_start (GTK_BOX (vbox), mugdata->statusbar, FALSE, FALSE, - 2); + mugdata->statusbar = mug_statusbar(); + gtk_box_pack_start(GTK_BOX(vbox), mugdata->statusbar, FALSE, FALSE, 2); - gtk_container_add (GTK_CONTAINER (mugdata->win), vbox); - gtk_widget_show_all (vbox); + gtk_container_add(GTK_CONTAINER(mugdata->win), vbox); + gtk_widget_show_all(vbox); - gtk_window_set_default_size (GTK_WINDOW (mugdata->win), 700, 500); - gtk_window_set_resizable (GTK_WINDOW (mugdata->win), TRUE); + gtk_window_set_default_size(GTK_WINDOW(mugdata->win), 700, 500); + gtk_window_set_resizable(GTK_WINDOW(mugdata->win), TRUE); { - gchar *icon; - icon = g_strdup_printf ("%s%cmug.svg", - MUGDIR, G_DIR_SEPARATOR); - gtk_window_set_icon_from_file (GTK_WINDOW (mugdata->win), icon, NULL); - g_free (icon); + gchar* icon; + icon = g_strdup_printf("%s%cmug.svg", MUGDIR, G_DIR_SEPARATOR); + gtk_window_set_icon_from_file(GTK_WINDOW(mugdata->win), icon, NULL); + g_free(icon); } return mugdata->win; } static gint -on_focus_query_bar (GtkWidget* ignored, GdkEventKey *event, MugData* mugdata) +on_focus_query_bar(GtkWidget* ignored, GdkEventKey* event, MugData* mugdata) { - if (event->type==GDK_KEY_RELEASE && event->keyval==GDK_KEY_Escape) { - mug_query_bar_grab_focus (MUG_QUERY_BAR (mugdata->querybar)); + if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_KEY_Escape) { + mug_query_bar_grab_focus(MUG_QUERY_BAR(mugdata->querybar)); return 1; } return 0; } int -main (int argc, char *argv[]) +main(int argc, char* argv[]) { - MugData mugdata; - GtkWidget *mugshell; - GOptionContext *octx; - GOptionEntry entries[] = { - {"muhome", 0, 0, G_OPTION_ARG_FILENAME, &mugdata.muhome, - "specify an alternative mu directory", NULL}, - {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} /* sentinel */ - }; + MugData mugdata; + GtkWidget* mugshell; + GOptionContext* octx; + GOptionEntry entries[] = { + {"muhome", + 0, + 0, + G_OPTION_ARG_FILENAME, + &mugdata.muhome, + "specify an alternative mu directory", + NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} /* sentinel */ + }; - gtk_init (&argc, &argv); + gtk_init(&argc, &argv); - octx = g_option_context_new ("- mug options"); - g_option_context_add_main_entries (octx, entries, "Mug"); + octx = g_option_context_new("- mug options"); + g_option_context_add_main_entries(octx, entries, "Mug"); - memset (&mugdata, 0, sizeof (MugData)); - if (!g_option_context_parse (octx, &argc, &argv, NULL)) { - g_option_context_free (octx); - g_printerr ("mug: error in options\n"); + memset(&mugdata, 0, sizeof(MugData)); + if (!g_option_context_parse(octx, &argc, &argv, NULL)) { + g_option_context_free(octx); + g_printerr("mug: error in options\n"); return 1; } - g_option_context_free (octx); - mu_runtime_init (mugdata.muhome, "mug", FALSE); + g_option_context_free(octx); + mu_runtime_init(mugdata.muhome, "mug", FALSE); - mugshell = mug_shell (&mugdata); - g_signal_connect (G_OBJECT (mugshell), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - g_signal_connect (G_OBJECT (mugshell), "key_release_event", - G_CALLBACK ( on_focus_query_bar ), (gpointer)&mugdata ); + mugshell = mug_shell(&mugdata); + g_signal_connect(G_OBJECT(mugshell), "destroy", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect(G_OBJECT(mugshell), + "key_release_event", + G_CALLBACK(on_focus_query_bar), + (gpointer)&mugdata); - gtk_widget_show (mugshell); - mug_query_bar_grab_focus (MUG_QUERY_BAR (mugdata.querybar)); + gtk_widget_show(mugshell); + mug_query_bar_grab_focus(MUG_QUERY_BAR(mugdata.querybar)); - gtk_main (); - g_free (mugdata.muhome); + gtk_main(); + g_free(mugdata.muhome); - mu_runtime_uninit (); + mu_runtime_uninit(); return 0; }