mirror of https://github.com/djcb/mu.git
lib: replace MuFlags with Mu::MessageFlags
Modernize the ancient MuFlags code to C++17
This commit is contained in:
parent
c5538d5b14
commit
473134a7b1
|
@ -50,8 +50,6 @@ lib_mu=static_library(
|
||||||
'mu-xapian.hh',
|
'mu-xapian.hh',
|
||||||
'mu-maildir.cc',
|
'mu-maildir.cc',
|
||||||
'mu-maildir.hh',
|
'mu-maildir.hh',
|
||||||
'mu-flags.cc',
|
|
||||||
'mu-flags.hh',
|
|
||||||
'mu-msg-crypto.cc',
|
'mu-msg-crypto.cc',
|
||||||
'mu-msg-doc.cc',
|
'mu-msg-doc.cc',
|
||||||
'mu-msg-doc.hh',
|
'mu-msg-doc.hh',
|
||||||
|
@ -65,7 +63,8 @@ lib_mu=static_library(
|
||||||
'mu-msg-sexp.cc',
|
'mu-msg-sexp.cc',
|
||||||
'mu-msg.cc',
|
'mu-msg.cc',
|
||||||
'mu-msg.hh',
|
'mu-msg.hh',
|
||||||
'mu-message-priority.hh'
|
'mu-message-flags.hh',
|
||||||
|
'mu-message-flags.cc',
|
||||||
'mu-message-priority.hh',
|
'mu-message-priority.hh',
|
||||||
'mu-message-priority.cc'
|
'mu-message-priority.cc'
|
||||||
],
|
],
|
||||||
|
|
220
lib/mu-flags.cc
220
lib/mu-flags.cc
|
@ -1,220 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (C) 2011-2020 <djcb@djcbsoftware.nl>
|
|
||||||
**
|
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
|
||||||
** under the terms of the GNU General Public License as published by the
|
|
||||||
** Free Software Foundation; either version 3, or (at your option) any
|
|
||||||
** later version.
|
|
||||||
**
|
|
||||||
** This program is distributed in the hope that it will be useful,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
** GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License
|
|
||||||
** along with this program; if not, write to the Free Software Foundation,
|
|
||||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "mu-flags.hh"
|
|
||||||
|
|
||||||
using namespace Mu;
|
|
||||||
|
|
||||||
struct FlagInfo {
|
|
||||||
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 */
|
|
||||||
|
|
||||||
{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_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)
|
|
||||||
{
|
|
||||||
unsigned 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)
|
|
||||||
{
|
|
||||||
unsigned 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)
|
|
||||||
{
|
|
||||||
unsigned u;
|
|
||||||
|
|
||||||
g_return_val_if_fail(str, MU_FLAG_INVALID);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
unsigned 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)
|
|
||||||
{
|
|
||||||
unsigned 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)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const char* cur;
|
|
||||||
MuFlags flag;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (f == MU_FLAG_INVALID) {
|
|
||||||
if (ignore_invalid)
|
|
||||||
continue;
|
|
||||||
return MU_FLAG_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mu_flag_type(f) & types)
|
|
||||||
flag |= f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
char*
|
|
||||||
Mu::mu_flags_custom_from_str(const char* str)
|
|
||||||
{
|
|
||||||
char* custom;
|
|
||||||
const char* cur;
|
|
||||||
unsigned u;
|
|
||||||
|
|
||||||
g_return_val_if_fail(str, NULL);
|
|
||||||
|
|
||||||
for (cur = str, u = 0, custom = NULL; *cur; ++cur) {
|
|
||||||
MuFlags flag;
|
|
||||||
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)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* otherwise, add it to our custom string */
|
|
||||||
if (!custom)
|
|
||||||
custom = g_new0(char, strlen(str) + 1);
|
|
||||||
custom[u++] = *cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
return custom;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Mu::mu_flags_foreach(MuFlagsForeachFunc func, gpointer user_data)
|
|
||||||
{
|
|
||||||
unsigned u;
|
|
||||||
|
|
||||||
g_return_if_fail(func);
|
|
||||||
|
|
||||||
for (u = 0; u != G_N_ELEMENTS(FLAG_INFO); ++u)
|
|
||||||
func(FLAG_INFO[u].flag, user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
MuFlags
|
|
||||||
Mu::mu_flags_from_str_delta(const char* str, MuFlags oldflags, MuFlagType types)
|
|
||||||
{
|
|
||||||
const char* cur;
|
|
||||||
MuFlags newflags;
|
|
||||||
|
|
||||||
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]);
|
|
||||||
if (f == 0)
|
|
||||||
goto error;
|
|
||||||
if (*cur == '+')
|
|
||||||
newflags |= f;
|
|
||||||
else
|
|
||||||
newflags &= ~f;
|
|
||||||
++cur;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newflags;
|
|
||||||
error:
|
|
||||||
g_warning("invalid flag string");
|
|
||||||
return MU_FLAG_INVALID;
|
|
||||||
}
|
|
171
lib/mu-flags.hh
171
lib/mu-flags.hh
|
@ -1,171 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (C) 2011-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
|
||||||
**
|
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
|
||||||
** under the terms of the GNU General Public License as published by the
|
|
||||||
** Free Software Foundation; either version 3, or (at your option) any
|
|
||||||
** later version.
|
|
||||||
**
|
|
||||||
** This program is distributed in the hope that it will be useful,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
** GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License
|
|
||||||
** along with this program; if not, write to the Free Software Foundation,
|
|
||||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MU_FLAGS_HH__
|
|
||||||
#define MU_FLAGS_HH__
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <utils/mu-utils.hh>
|
|
||||||
|
|
||||||
namespace Mu {
|
|
||||||
|
|
||||||
enum MuFlags {
|
|
||||||
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,<fileinfo>",
|
|
||||||
* <fileinfo> 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,
|
|
||||||
|
|
||||||
/* decides on cur/ or new/ in the maildir */
|
|
||||||
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,
|
|
||||||
|
|
||||||
/* 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,
|
|
||||||
|
|
||||||
/* other content flags */
|
|
||||||
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_ENABLE_BITOPS(MuFlagType);
|
|
||||||
|
|
||||||
#define MU_FLAG_TYPE_ANY ((MuFlagType)-1)
|
|
||||||
#define MU_FLAG_TYPE_INVALID ((MuFlagType)-1)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the type of flag (mailfile, maildir, pseudo or content)
|
|
||||||
*
|
|
||||||
* @param flag a MuFlag
|
|
||||||
*
|
|
||||||
* @return the flag type or MU_FLAG_TYPE_INVALID in case of error
|
|
||||||
*/
|
|
||||||
MuFlagType mu_flag_type(MuFlags flag) G_GNUC_CONST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the flag character
|
|
||||||
*
|
|
||||||
* @param flag a MuFlag (single)
|
|
||||||
*
|
|
||||||
* @return the character, or 0 if it's not a valid flag
|
|
||||||
*/
|
|
||||||
char mu_flag_char(MuFlags flag) G_GNUC_CONST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the flag name
|
|
||||||
*
|
|
||||||
* @param flag a single MuFlag
|
|
||||||
*
|
|
||||||
* @return the name (don't free) as string or NULL in case of error
|
|
||||||
*/
|
|
||||||
const char* mu_flag_name(MuFlags flag) G_GNUC_CONST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the string representation of an OR'ed set of flags
|
|
||||||
*
|
|
||||||
* @param flags MuFlag (OR'ed)
|
|
||||||
* @param types allowable types (OR'ed) for the result; the rest is ignored
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the (OR'ed) flags corresponding to a string representation
|
|
||||||
*
|
|
||||||
* @param str the file info string
|
|
||||||
* @param types the flag types to accept (other will be ignored)
|
|
||||||
* @param ignore invalid if TRUE, ignore invalid flags, otherwise return
|
|
||||||
* MU_FLAG_INVALID if an invalid flag is encountered
|
|
||||||
*
|
|
||||||
* @return the (OR'ed) flags
|
|
||||||
*/
|
|
||||||
MuFlags mu_flags_from_str(const char* str, MuFlagType types, gboolean ignore_invalid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the MuFlag char for some flag name
|
|
||||||
*
|
|
||||||
* @param str a flag name
|
|
||||||
*
|
|
||||||
* @return a flag character, or 0
|
|
||||||
*/
|
|
||||||
MuFlags mu_flag_char_from_name(const char* str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return the concatenation of all non-standard file flags in str
|
|
||||||
* (ie., characters other than DFPRST) as a newly allocated string.
|
|
||||||
*
|
|
||||||
* @param str the file info string
|
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update #oldflags with the flags in #str, where #str consists of the
|
|
||||||
* the normal flag characters, but prefixed with either '+' or '-',
|
|
||||||
* which means resp. "add this flag" or "remove this flag" from
|
|
||||||
* oldflags. So, e.g. "-N+S" would unset the NEW flag and set the
|
|
||||||
* SEEN flag, without affecting other flags.
|
|
||||||
*
|
|
||||||
* @param str the string representation
|
|
||||||
* @param old flags to update
|
|
||||||
* @param types the flag types to accept (other will be ignored)
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MuFlags mu_flags_from_str_delta(const char* str, MuFlags oldflags, MuFlagType types);
|
|
||||||
|
|
||||||
typedef void (*MuFlagsForeachFunc)(MuFlags flag, gpointer user_data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* call a function for each available flag
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
} // namespace Mu
|
|
||||||
|
|
||||||
#endif /*__MU_FLAGS_H__*/
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify it
|
||||||
|
** under the terms of the GNU General Public License as published by the
|
||||||
|
** Free Software Foundation; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* implementation is almost completely in the header; here we just add some
|
||||||
|
* compile-time tests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mu-message-flags.hh"
|
||||||
|
|
||||||
|
using namespace Mu;
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Mu::message_flags_to_string(MessageFlags flags)
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
for (auto&& info: AllMessageFlagInfos)
|
||||||
|
if (any_of(info.flag & flags))
|
||||||
|
str+=info.shortcut;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flags & flag-info
|
||||||
|
*/
|
||||||
|
constexpr bool
|
||||||
|
validate_message_info_flags()
|
||||||
|
{
|
||||||
|
for (auto id = 0U; id != AllMessageFlagInfos.size(); ++id) {
|
||||||
|
const auto flag = static_cast<MessageFlags>(1 << id);
|
||||||
|
if (flag != AllMessageFlagInfos[id].flag)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(AllMessageFlagInfos.size() ==
|
||||||
|
__builtin_ctz(static_cast<unsigned>(MessageFlags::_final_)));
|
||||||
|
static_assert(validate_message_info_flags());
|
||||||
|
|
||||||
|
static_assert(!!message_flag_info(MessageFlags::Encrypted));
|
||||||
|
static_assert(!message_flag_info(MessageFlags::None));
|
||||||
|
static_assert(!message_flag_info(static_cast<MessageFlags>(0)));
|
||||||
|
static_assert(!message_flag_info(static_cast<MessageFlags>(1<<AllMessageFlagInfos.size())),
|
||||||
|
"should be invalid");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* message_flag_info
|
||||||
|
*/
|
||||||
|
static_assert(message_flag_info('D')->flag == MessageFlags::Draft);
|
||||||
|
static_assert(message_flag_info('l')->flag == MessageFlags::MailingList);
|
||||||
|
static_assert(!message_flag_info('q'));
|
||||||
|
|
||||||
|
static_assert(message_flag_info("trashed")->flag == MessageFlags::Trashed);
|
||||||
|
static_assert(message_flag_info("attach")->flag == MessageFlags::HasAttachment);
|
||||||
|
static_assert(!message_flag_info("fnorb"));
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* message_flags_from_expr
|
||||||
|
*/
|
||||||
|
static_assert(message_flags_from_absolute_expr("SRP").value() ==
|
||||||
|
(MessageFlags::Seen | MessageFlags::Replied | MessageFlags::Passed));
|
||||||
|
static_assert(message_flags_from_absolute_expr("Faul").value() ==
|
||||||
|
(MessageFlags::Flagged | MessageFlags::Unread |
|
||||||
|
MessageFlags::HasAttachment | MessageFlags::MailingList));
|
||||||
|
|
||||||
|
static_assert(!message_flags_from_absolute_expr("DRT?"));
|
||||||
|
static_assert(message_flags_from_absolute_expr("DRT?", true/*ignore invalid*/).value() ==
|
||||||
|
(MessageFlags::Draft | MessageFlags::Replied |
|
||||||
|
MessageFlags::Trashed));
|
||||||
|
static_assert(message_flags_from_absolute_expr("DFPNxulabcdef", true/*ignore invalid*/).value() ==
|
||||||
|
(MessageFlags::Draft|MessageFlags::Flagged|MessageFlags::Passed|
|
||||||
|
MessageFlags::New | MessageFlags::Encrypted |
|
||||||
|
MessageFlags::Unread | MessageFlags::MailingList |
|
||||||
|
MessageFlags::HasAttachment));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* message_flags_from_delta_expr
|
||||||
|
*/
|
||||||
|
static_assert(message_flags_from_delta_expr(
|
||||||
|
"+S-u-N", MessageFlags::New|MessageFlags::Unread).value() ==
|
||||||
|
MessageFlags::Seen);
|
||||||
|
static_assert(message_flags_from_delta_expr("+R+P-F", MessageFlags::Seen).value() ==
|
||||||
|
(MessageFlags::Seen|MessageFlags::Passed|MessageFlags::Replied));
|
||||||
|
/* '-B' is invalid */
|
||||||
|
static_assert(!message_flags_from_delta_expr("+R+P-B", MessageFlags::Seen));
|
||||||
|
/* '-B' is invalid, but ignore invalid */
|
||||||
|
static_assert(message_flags_from_delta_expr("+R+P-B", MessageFlags::Seen, true) ==
|
||||||
|
(MessageFlags::Replied|MessageFlags::Passed|MessageFlags::Seen));
|
||||||
|
static_assert(message_flags_from_delta_expr("+F+T-S", MessageFlags::None, true).value() ==
|
||||||
|
(MessageFlags::Flagged|MessageFlags::Trashed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* message_flags_filter
|
||||||
|
*/
|
||||||
|
static_assert(message_flags_filter(message_flags_from_absolute_expr(
|
||||||
|
"DFPNxulabcdef", true/*ignore invalid*/).value(),
|
||||||
|
MessageFlagCategory::Mailfile) ==
|
||||||
|
(MessageFlags::Draft|MessageFlags::Flagged|MessageFlags::Passed));
|
|
@ -0,0 +1,308 @@
|
||||||
|
/*
|
||||||
|
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** This program is free software; you can redistribute it and/or modify it
|
||||||
|
** under the terms of the GNU General Public License as published by the
|
||||||
|
** Free Software Foundation; either version 3, or (at your option) any
|
||||||
|
** later version.
|
||||||
|
**
|
||||||
|
** This program is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with this program; if not, write to the Free Software Foundation,
|
||||||
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MU_MESSAGE_FLAGS_HH__
|
||||||
|
#define MU_MESSAGE_FLAGS_HH__
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
|
#include "utils/mu-utils.hh"
|
||||||
|
|
||||||
|
namespace Mu {
|
||||||
|
|
||||||
|
enum struct MessageFlags {
|
||||||
|
None = 0, /**< No flags */
|
||||||
|
/**
|
||||||
|
* next 6 are seen in the file-info part of maildir message file
|
||||||
|
* names, ie., in a name like "1234345346:2,<fileinfo>",
|
||||||
|
* <fileinfo> consists of zero or more of the following
|
||||||
|
* characters (in ascii order)
|
||||||
|
*/
|
||||||
|
Draft = 1 << 0, /**< A draft message */
|
||||||
|
Flagged = 1 << 1, /**< A flagged message */
|
||||||
|
Passed = 1 << 2, /**< A passed (forwarded) message */
|
||||||
|
Replied = 1 << 3, /**< A replied message */
|
||||||
|
Seen = 1 << 4, /**< A seen (read) message */
|
||||||
|
Trashed = 1 << 5, /**< A trashed message */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decides on cur/ or new/ in the maildir
|
||||||
|
*/
|
||||||
|
New = 1 << 6, /**< A new message */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* content flags -- not visible in the filename, but used for
|
||||||
|
* searching
|
||||||
|
*/
|
||||||
|
Signed = 1 << 7, /**< Cryptographically signed */
|
||||||
|
Encrypted = 1 << 8, /**< Encrypted */
|
||||||
|
HasAttachment = 1 << 9, /**< Has an attachment */
|
||||||
|
|
||||||
|
Unread = 1 << 10, /**< Unread; pseudo-flag, only for queries, so
|
||||||
|
* we can search for flag:unread, which is
|
||||||
|
* equivalent to 'flag:new OR NOT
|
||||||
|
* flag:seen' */
|
||||||
|
/**
|
||||||
|
* other content flags
|
||||||
|
*/
|
||||||
|
MailingList = 1 << 11,/**< A mailing-list message */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <private>
|
||||||
|
*/
|
||||||
|
_final_ = 1 << 12
|
||||||
|
};
|
||||||
|
MU_ENABLE_BITOPS(MessageFlags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message flags category
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum struct MessageFlagCategory {
|
||||||
|
None, /**< Nothing */
|
||||||
|
Mailfile, /**< Flag for a message file */
|
||||||
|
Maildir, /**< Flag for message file's location */
|
||||||
|
Content, /**< Message content flag */
|
||||||
|
Pseudo /**< Pseuodo flag */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info about invidual message flags
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct MessageFlagInfo {
|
||||||
|
MessageFlags flag; /**< The message flag */
|
||||||
|
char shortcut; /**< Shortcut character */
|
||||||
|
std::string_view name; /**< Name of the flag */
|
||||||
|
MessageFlagCategory category; /**< Flag category */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of all flag information.
|
||||||
|
*/
|
||||||
|
constexpr std::array<MessageFlagInfo, 12>
|
||||||
|
AllMessageFlagInfos = {{
|
||||||
|
{MessageFlags::Draft, 'D', "draft", MessageFlagCategory::Mailfile},
|
||||||
|
{MessageFlags::Flagged, 'F', "flagged", MessageFlagCategory::Mailfile},
|
||||||
|
{MessageFlags::Passed, 'P', "passed", MessageFlagCategory::Mailfile},
|
||||||
|
{MessageFlags::Replied, 'R', "replied", MessageFlagCategory::Mailfile},
|
||||||
|
{MessageFlags::Seen, 'S', "seen", MessageFlagCategory::Mailfile},
|
||||||
|
{MessageFlags::Trashed, 'T', "trashed", MessageFlagCategory::Mailfile},
|
||||||
|
|
||||||
|
{MessageFlags::New, 'N', "new", MessageFlagCategory::Maildir},
|
||||||
|
|
||||||
|
{MessageFlags::Signed, 'z', "signed", MessageFlagCategory::Content},
|
||||||
|
{MessageFlags::Encrypted, 'x', "encrypted", MessageFlagCategory::Content},
|
||||||
|
{MessageFlags::HasAttachment, 'a', "attach", MessageFlagCategory::Content},
|
||||||
|
|
||||||
|
{MessageFlags::Unread, 'u', "unread", MessageFlagCategory::Pseudo},
|
||||||
|
|
||||||
|
{MessageFlags::MailingList, 'l', "list", MessageFlagCategory::Content},
|
||||||
|
}};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get flag info for some flag
|
||||||
|
*
|
||||||
|
* @param flag a singular flag
|
||||||
|
*
|
||||||
|
* @return the MessageFlagInfo, or std::nullopt in case of error.
|
||||||
|
*/
|
||||||
|
constexpr const std::optional<MessageFlagInfo>
|
||||||
|
message_flag_info(MessageFlags flag)
|
||||||
|
{
|
||||||
|
constexpr auto upper = static_cast<unsigned>(MessageFlags::_final_);
|
||||||
|
const auto val = static_cast<unsigned>(flag);
|
||||||
|
|
||||||
|
if (__builtin_popcount(val) != 1 || val >= upper)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return AllMessageFlagInfos[static_cast<unsigned>(__builtin_ctz(val))];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get flag info for some flag
|
||||||
|
*
|
||||||
|
* @param shortcut shortcut character
|
||||||
|
*
|
||||||
|
* @return the MessageFlagInfo
|
||||||
|
*/
|
||||||
|
constexpr const std::optional<MessageFlagInfo>
|
||||||
|
message_flag_info(char shortcut)
|
||||||
|
{
|
||||||
|
for (auto&& info: AllMessageFlagInfos)
|
||||||
|
if (info.shortcut == shortcut)
|
||||||
|
return info;
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get flag info for some flag
|
||||||
|
*
|
||||||
|
* @param name of the message-flag.
|
||||||
|
*
|
||||||
|
* @return the MessageFlagInfo
|
||||||
|
*/
|
||||||
|
constexpr const std::optional<MessageFlagInfo>
|
||||||
|
message_flag_info(std::string_view name)
|
||||||
|
{
|
||||||
|
for (auto&& info: AllMessageFlagInfos)
|
||||||
|
if (info.name == name)
|
||||||
|
return info;
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There are two string-based expression types for flags:
|
||||||
|
* 1) 'absolute': replace the existing flags
|
||||||
|
* 2_ 'delta' : flags as a delta of existing flags.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the (OR'ed) flags corresponding to an expression.
|
||||||
|
*
|
||||||
|
* @param expr the expression (a sequence of flag shortcut characters)
|
||||||
|
* @param ignore_invalid if @true, ignore invalid flags, otherwise return
|
||||||
|
* nullopt if an invalid flag is encountered
|
||||||
|
*
|
||||||
|
* @return the (OR'ed) flags or MessageFlags::None
|
||||||
|
*/
|
||||||
|
constexpr std::optional<MessageFlags>
|
||||||
|
message_flags_from_absolute_expr(std::string_view expr,
|
||||||
|
bool ignore_invalid=false)
|
||||||
|
{
|
||||||
|
MessageFlags flags{MessageFlags::None};
|
||||||
|
|
||||||
|
for (auto&& kar: expr) {
|
||||||
|
if (const auto& info{message_flag_info(kar)}; !info) {
|
||||||
|
if (!ignore_invalid)
|
||||||
|
return std::nullopt;
|
||||||
|
} else
|
||||||
|
flags |= info->flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate flags from existing flags and a delta expression
|
||||||
|
*
|
||||||
|
* Update @p flags with the flags in @p expr, where @p exprt consists of the the
|
||||||
|
* normal flag shortcut characters, prefixed with either '+' or '-', which means
|
||||||
|
* resp. "add this flag" or "remove this flag".
|
||||||
|
*
|
||||||
|
* So, e.g. "-N+S" would unset the NEW flag and set the SEEN flag, without
|
||||||
|
* affecting other flags.
|
||||||
|
*
|
||||||
|
* @param expr delta expression
|
||||||
|
* @param flags existing flags
|
||||||
|
* @param ignore_invalid if @true, ignore invalid flags, otherwise return
|
||||||
|
* nullopt if an invalid flag is encountered
|
||||||
|
*
|
||||||
|
* @return new flags, or nullopt in case of error
|
||||||
|
*/
|
||||||
|
constexpr std::optional<MessageFlags>
|
||||||
|
message_flags_from_delta_expr(std::string_view expr, MessageFlags flags,
|
||||||
|
bool ignore_invalid=false)
|
||||||
|
{
|
||||||
|
if (expr.size() % 2 != 0)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
for (auto u = 0U; u != expr.size(); u+=2) {
|
||||||
|
|
||||||
|
if (const auto& info{message_flag_info(expr[u+1])}; !info) {
|
||||||
|
if (!ignore_invalid)
|
||||||
|
return std::nullopt;
|
||||||
|
} else {
|
||||||
|
switch(expr[u]) {
|
||||||
|
case '+':
|
||||||
|
flags |= info->flag;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
flags &= ~info->flag;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!ignore_invalid)
|
||||||
|
return std::nullopt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the flags from either 'absolute' or 'delta' expressions
|
||||||
|
*
|
||||||
|
* @param expr a flag expression, either 'delta' or 'absolute'
|
||||||
|
* @param flags optional: existing flags or none. Required for delta.
|
||||||
|
*
|
||||||
|
* @return either messages flags or std::nullopt in case of error.
|
||||||
|
*/
|
||||||
|
constexpr std::optional<MessageFlags>
|
||||||
|
message_flags_from_expr(std::string_view expr,
|
||||||
|
std::optional<MessageFlags> flags=std::nullopt)
|
||||||
|
{
|
||||||
|
if (expr.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
if (expr[0] == '+' || expr[0] == '-')
|
||||||
|
return message_flags_from_delta_expr(
|
||||||
|
expr, flags.value_or(MessageFlags::None), true);
|
||||||
|
else
|
||||||
|
return message_flags_from_absolute_expr(expr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter out flags which are not in the given category
|
||||||
|
*
|
||||||
|
* @param flags flags
|
||||||
|
* @param cat category
|
||||||
|
*
|
||||||
|
* @return filter flags
|
||||||
|
*/
|
||||||
|
constexpr MessageFlags
|
||||||
|
message_flags_filter(MessageFlags flags, MessageFlagCategory cat)
|
||||||
|
{
|
||||||
|
for (auto&& info: AllMessageFlagInfos)
|
||||||
|
if (info.category != cat)
|
||||||
|
flags &= ~info.flag;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string representation of flags
|
||||||
|
*
|
||||||
|
* @param flags flags
|
||||||
|
*
|
||||||
|
* @return string as a sequence of message-flag shortcuts
|
||||||
|
*/
|
||||||
|
std::string message_flags_to_string(MessageFlags flags);
|
||||||
|
|
||||||
|
} // namepace Mu
|
||||||
|
|
||||||
|
#endif /* MU_MESSAGE_FLAGS_HH__ */
|
|
@ -1,193 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
|
||||||
**
|
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
|
||||||
** under the terms of the GNU General Public License as published by the
|
|
||||||
** Free Software Foundation; either version 3, or (at your option) any
|
|
||||||
** later version.
|
|
||||||
**
|
|
||||||
** This program is distributed in the hope that it will be useful,
|
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
** GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License
|
|
||||||
** along with this program; if not, write to the Free Software Foundation,
|
|
||||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif /*HAVE_CONFIG_H*/
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include "mu-flags.hh"
|
|
||||||
#include "test-mu-common.hh"
|
|
||||||
|
|
||||||
using namespace Mu;
|
|
||||||
|
|
||||||
static 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
/* 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_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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("",
|
|
||||||
(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));
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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}};
|
|
||||||
|
|
||||||
for (u = 0; u != G_N_ELEMENTS(cases); ++u) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
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_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();
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
Loading…
Reference in New Issue