297void trim(std::string& value)
 
  301        size_t i(value.length());
 
  304            const char c(value[i - 1]);
 
  305            if(c != 
' ' && c != 
'\r' && c != 
'\n' && c != 
'\t')
 
  323bool is_quoted_char(
char c)
 
  328    return c == 
'\t' || c >= 
' ' && c != 0x7F;
 
  341bool is_atom_char(
char c)
 
  343    return (c >= 
'A' && c <= 
'Z')
 
  344        || (c >= 
'a' && c <= 
'z')
 
  345        || (c >= 
'0' && c <= 
'9')
 
  346        || c == 
'!' || c == 
'#' 
  347        || c == 
'$' || c == 
'%' 
  348        || c == 
'&' || c == 
'\'' 
  349        || c == 
'*' || c == 
'+' 
  350        || c == 
'-' || c == 
'/' 
  351        || c == 
'=' || c == 
'?' 
  352        || c == 
'^' || c == 
'_' 
  353        || c == 
'`' || c == 
'{' 
  354        || c == 
'|' || c == 
'}' 
  424    char const * start(
f_input.c_str());
 
  426    char const * s(start);
 
  427    for(; *s != 
'\0'; ++s)
 
  447                for(; end > start; --end)
 
  449                    char const c(end[-1]);
 
  450                    if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
  457                    std::string 
const e(start, end - start);
 
  484                for(; end > start; --end)
 
  486                    char const c(end[-1]);
 
  487                    if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
  498                std::string 
const last_group(start, end - start);
 
  521                for(; end > start; --end)
 
  523                    char const c(end[-1]);
 
  524                    if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
  531                    std::string 
const e(start, end - start);
 
  548            for(++s; *s != 
'\0' && *s != 
'"'; ++s)
 
  552                    if(!is_quoted_char(s[1]))
 
  572                int comment_count(1);
 
  573                for(++s; *s != 
'\0'; ++s)
 
  577                        if(!is_quoted_char(s[1]))
 
  592                        if(comment_count <= 0)
 
  608            for(++s; *s != 
']'; ++s)
 
  610                if(*s == 
'\0' || *s == 
'[' || *s == 
'\\')
 
  634        for(; end > start; --end)
 
  636            char const c(end[-1]);
 
  637            if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
  644            std::string 
const e(start, end - start);
 
 
  715    bool apply_quotes(
false);
 
  718    char const * extra(
"");
 
  719    char const * escape(
"");
 
  749        char const * s(str.c_str());
 
  750        for(; *s != 
'\0'; ++s)
 
  752            if(!is_atom_char(*s) && strchr(extra, *s) == 
nullptr)
 
  757        apply_quotes = *s != 
'\0';
 
  763        for(
const char *s(str.c_str()); *s != 
'\0'; ++s)
 
  765            if(strchr(escape, *s) != 
nullptr)
 
 
  892    for(
const char *u(name.c_str()); *u != 
'\0' && *u != 
':'; ++u)
 
  894        if(*u >= 
'a' && *u <= 
'z')
 
  898        else if((*u >= 
'A' && *u <= 
'Z')
 
  899             || (*u >= 
'0' && *u <= 
'9')
 
  910    if(uname.empty() || uname[0] < 
'A' || uname[0] > 
'Z')
 
  916    || uname == 
"RESENT-FROM")
 
  921    || uname == 
"RESENT-SENDER")
 
  927    || uname == 
"REPLY-TO" 
  928    || uname == 
"RESENT-TO" 
  929    || uname == 
"RESENT-CC")
 
  934    || uname == 
"RESENT-BCC")
 
 
  978    value.reserve(email.length());
 
  979    std::string fullname;
 
  980    std::string username;
 
  983    bool has_angle(
false);
 
  984    bool found_at(
false);
 
  985    bool found_dot(
false);
 
  987    char const * start(email.c_str());
 
  988    char const * s(start);
 
  989    for(; *s != 
'\0'; ++s)
 
  998            for(++s; *s != 
'"'; ++s)
 
 1002                    throw std::logic_error(
"somehow we found a \\0 in a quoted string in tld_email_t which should not happen since it was already checked validity in tld_email_t::parse()");
 
 1013                        throw std::logic_error(
"somehow we found a \\0 in a quoted string after a backslash in tld_email_t which should not happen since it was already checked validity in tld_email_t::parse()"); 
 
 1016                if((
static_cast<unsigned char>(*s) < 
' ' && *s != 
'\t') || *s == 0x7F)
 
 1032            if( *s != 
'<' && *s != 
'@' )
 
 1044            for(++s; 
count > 0; ++s)
 
 1050                    throw std::logic_error(
"somehow we found a \\0 in a comment in tld_email_t which should not happen since it was already checked in tld_email_t::parse()");
 
 1068                    if(!is_quoted_char(*s))
 
 1070                        throw std::logic_error(
"somehow we found a non-quotable character after a backslash (\\) in tld_email_t which should not happen since it was already checked in tld_email_t::parse()");
 
 1076                if(
static_cast<unsigned char>(c) < 
' ')
 
 1087            if(!found_at || done || !value.empty() || !domain.empty())
 
 1095            for(++s; *s != 
']'; ++s)
 
 1098                if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
 1103            for(; *s != 
'[' && *s != 
'\\' && *s != 
']' && *s != 
' ' && *s != 
'\n' && *s != 
'\r' && *s != 
'\t'; ++s)
 
 1107                    throw std::logic_error(
"somehow we found a \\0 in a literal domain in tld_email_t which should not happen since it was already checked in tld_email_t::parse()");
 
 1111                if(
static_cast<unsigned char>(*s) < 
' ' || *s == 0x7F)
 
 1121            for(; *s != 
'[' && *s != 
'\\' && *s != 
']'; ++s)
 
 1124                if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
 1129            if(*s != 
']' || value.empty())
 
 1137            || *value.rbegin() == 
'.' 
 1138            || value.find(
"..") != std::string::npos)
 
 1150            if(has_angle || found_at || found_dot || done)
 
 1172            if(!has_angle || !found_at || done)
 
 1205            if(found_at || done)
 
 1230            if( !value.empty() )
 
 1239            for(++s; *s != 
'\0'; ++s)
 
 1242                if(c != 
' ' && c != 
'\n' && c != 
'\r' && c != 
'\t')
 
 1252            || (!value.empty() && *value.rbegin() == 
'.')   
 
 1253            || s[1] == 
'@' || s[1] == 
'>')                  
 
 1264            if(!is_atom_char(*s))
 
 1276    if(username.empty() || has_angle)
 
 1322    std::unique_ptr<char, void(*)(
char *)> lowercase_domain(
tld_domain_to_lowercase(domain.c_str()), 
reinterpret_cast<void(*)(
char *)
>(&::free));
 
 1331    auto has_whitespace = [&]( 
char c )
 
 1333            return (c == 
' ' || c == 
'\n' || c == 
'\r' || c == 
'\t');
 
 1335    if( std::find_if( std::begin(username), std::end(username), has_whitespace ) != std::end(username) )
 
 1340    if( std::find_if( std::begin(domain), std::end(domain), has_whitespace ) != std::end(domain) )
 
 1354    if(fullname.empty())
 
 
 1391    char const * s(group.c_str());
 
 1395    for(; *s != 
'\0'; ++s)
 
 1407            for(++s; *s == 
' ' || *s == 
'\n' || *s == 
'\r' || *s == 
'\t'; ++s);
 
 1413#pragma GCC diagnostic push 
 1414#pragma GCC diagnostic ignored "-Wstrict-overflow" 
 1415            for(++s; 
count > 0; ++s)
 
 1416#pragma GCC diagnostic pop
 
 1420                    throw std::logic_error(
"somehow we found a \\0 in a quoted string in tld_email_t which should not happen since it was already checked in tld_email_t::parse()");
 
 1433                    if(!is_quoted_char(s[1]))
 
 1435                        throw std::logic_error(
"somehow we found a non-quotable character in tld_email_t which should not happen since it was already checked in tld_email_t::parse()");
 
 1448            if(
static_cast<unsigned char>(*s) < 
' ' || *s == 0x7F)
 
 
 1527    return list->count();
 
 
 1561    return list->next(e) ? 1 : 0;
 
 
std::string f_email_only
The complete email address without display name.
tld_result parse(const std::string &email)
Parse one email to a tld_email_t object.
std::string f_canonicalized_email
The email including the display name.
std::string f_domain
The domain part of the email address.
tld_result parse_group(const std::string &group)
Parse a group including comments.
std::string f_username
The user being named in this email address.
std::string f_fullname
The user full or display name.
std::string f_group
The group this emails was defined in.
std::string f_original_email
The email as read from the source.
The C++ side of the email list implementation.
tld_result f_result
The result of the parse() function.
int f_flags
The flags as passed to the parse() function.
void rewind() const
Rewind the reader to the start of the list.
tld_result parse(const std::string &emails, int flags)
Parse a new list of emails.
static tld_email_field_type email_field_type(const std::string &name)
Check whether a name represents a field with a list of emails.
int count() const
Return the number of emails recorded.
tld_email_list_t f_email_list
The list of emails.
std::string f_last_group
The last group read in the input.
std::string f_input
The input string of the last call to parse().
void parse_all_emails()
Parse all the emails in f_input.
tld_email_list()
Initialize the tld_email_list object.
int f_pos
The current position reading the emails.
bool next(tld_email_t &e) const
Retrieve a copy of the next email information.
static std::string quote_string(const std::string &name, char quote)
Transform a name if it requires quotation.
const char * f_group
The group this emails was defined in.
const char * f_canonicalized_email
The email including the display name.
const char * f_original_email
The email as read from the source.
const char * f_email_only
The complete email address without display name.
const char * f_username
The user being named in this email address.
const char * f_domain
The domain part of the email address.
const char * f_fullname
The user full or display name.
Set of information returned by the tld() function.
The public header of the libtld library.
LIBTLD_EXPORT char * tld_domain_to_lowercase(const char *domain)
Transform a domain with a TLD to lowercase before processing.
@ TLD_EMAIL_FIELD_TYPE_UNKNOWN
The input does not represent valid emails.
@ TLD_EMAIL_FIELD_TYPE_ADDRESS_LIST
The input represents a mandatory list of mailboxes.
@ TLD_EMAIL_FIELD_TYPE_MAILBOX
The input represents a mailbox.
@ TLD_EMAIL_FIELD_TYPE_ADDRESS_LIST_OPT
The input represents an optional list of email addresses.
@ TLD_EMAIL_FIELD_TYPE_INVALID
The input of email_field_type() was not valid.
@ TLD_EMAIL_FIELD_TYPE_MAILBOX_LIST
The input represents a mailbox list.
LIBTLD_EXPORT void tld_email_free(struct tld_email_list *list)
Free the list of emails.
LIBTLD_EXPORT enum tld_result tld(const char *uri, struct tld_info *info)
Get information about the TLD for the specified URI.
LIBTLD_EXPORT void tld_email_rewind(struct tld_email_list *list)
Rewind the reading of the emails.
LIBTLD_EXPORT struct tld_email_list * tld_email_alloc()
Allocate a list of emails object.
LIBTLD_EXPORT int tld_email_count(struct tld_email_list *list)
Return the number of emails found after a parse.
LIBTLD_EXPORT enum tld_result tld_email_parse(struct tld_email_list *list, const char *emails, int flags)
Parse a list of emails in the email list object.
@ TLD_RESULT_SUCCESS
Success! The TLD of the specified URI is valid.
@ TLD_RESULT_INVALID
The TLD was found, but it is marked as invalid.
@ TLD_RESULT_NULL
The input URI is empty.
LIBTLD_EXPORT int tld_email_next(struct tld_email_list *list, struct tld_email *e)
Retrieve the next email.
void list()
List the default schemes accepted.