mu/lib/message/mu-contact.hh

213 lines
5.3 KiB
C++

/*
** 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_CONTACT_HH__
#define MU_MESSAGE_CONTACT_HH__
#include <functional>
#include <string>
#include <vector>
#include <functional>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <utils/mu-option.hh>
#include "mu-fields.hh"
struct _InternetAddressList;
namespace Mu {
/**
* Get the hash value for a lowercase value of s; useful for email-addresses
*
* @param s a string
*
* @return a hash value.
*/
size_t lowercase_hash(const std::string& s);
struct Contact {
enum struct Type {
None, Sender, From, ReplyTo, To, Cc, Bcc
};
/**
* Construct a new Contact
*
* @param email_ email address
* @param name_ name or empty
* @param type_ contact field type
* @param message_date_ data for the message for this contact
*/
Contact(const std::string& email_, const std::string& name_ = "",
Type type_ = Type::None, ::time_t message_date_ = 0)
: email{email_}, name{name_}, type{type_},
message_date{message_date_}, personal{}, frequency{1}, tstamp{}
{ cleanup_name(); }
/**
* Construct a new Contact
*
* @param email_ email address
* @param name_ name or empty
* @param message_date_ date of message this contact originate from
* @param personal_ is this a personal contact?
* @param freq_ how often was this contact seen?
* @param tstamp_ timestamp for last change
*/
Contact(const std::string& email_, const std::string& name_,
time_t message_date_, bool personal_, size_t freq_,
int64_t tstamp_)
: email{email_}, name{name_}, type{Type::None},
message_date{message_date_}, personal{personal_}, frequency{freq_},
tstamp{tstamp_}
{ cleanup_name();}
/**
* Get the "display name" for this contact; basically, if there's a
* non-empty name, it's
* Jane Doe <email@example.com>
* otherwise it's just the e-mail address.
*
* @param quote_if_needed if true, handle quoting of the name-part as well. This
* is useful when the address is to be used directly in emails.
*
* @return the display name
*/
std::string display_name(bool quote_if_needed=false) const;
/**
* Operator==; based on the hash values (ie. lowercase e-mail address)
*
* @param rhs some other Contact
*
* @return true orf false.
*/
bool operator== (const Contact& rhs) const noexcept {
return hash() == rhs.hash();
}
/**
* Get a hash-value for this contact, which gets lazily calculated. This
* * is for use with container classes. This uses the _lowercase_ email
* address.
*
* @return the hash
*/
size_t hash() const {
static size_t cached_hash;
if (cached_hash == 0) {
cached_hash = lowercase_hash(email);
}
return cached_hash;
}
/**
* Get the corresponding Field::Id (if any)
* for this contact.
*
* @return the field-id or Nothing.
*/
constexpr Option<Field::Id> field_id() const noexcept {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch(type) {
case Type::Bcc:
return Field::Id::Bcc;
case Type::Cc:
return Field::Id::Cc;
case Type::From:
return Field::Id::From;
case Type::To:
return Field::Id::To;
default:
return Nothing;
}
#pragma GCC diagnostic pop
}
/*
* data members
*/
std::string email; /**< Email address for this contact.Not empty */
std::string name; /**< Name for this contact; can be empty. */
Type type; /**< Type of contact */
int64_t message_date; /**< date of the contact's message */
bool personal; /**< A personal message? */
size_t frequency; /**< Frequency of this contact */
int64_t tstamp; /**< Timestamp for this contact (internal use) */
private:
void cleanup_name() { // replace control characters by spaces.
for (auto& c: name)
if (iscntrl(c))
c = ' ';
}
};
constexpr Option<Contact::Type>
contact_type_from_field_id(Field::Id id) noexcept {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch(id) {
case Field::Id::Bcc:
return Contact::Type::Bcc;
case Field::Id::Cc:
return Contact::Type::Cc;
case Field::Id::From:
return Contact::Type::From;
case Field::Id::To:
return Contact::Type::To;
default:
return Nothing;
}
#pragma GCC diagnostic pop
}
using Contacts = std::vector<Contact>;
/**
* Get contacts as a comma-separated list.
*
* @param contacts contacs
*
* @return string with contacts.
*/
std::string to_string(const Contacts& contacts);
} // namespace Mu
/**
* Implement our hash int std::
*/
template<> struct std::hash<Mu::Contact> {
std::size_t operator()(const Mu::Contact& c) const noexcept {
return c.hash();
}
};
#endif /* MU_CONTACT_HH__ */