// // File: hzEmaddr.cpp // Purpose: Implimentation of the hzEmaddr (email address) class. // // Legal Notice: This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#include <iostream> #include <stdarg.h>
#include "hzChars.h" #include "hzTextproc.h" #include "hzProcess.h" #include "hzSSR.h"
/* ** Variables */
global hzSet<hzDomain> _hzGlobal_setDomains ; // Repository of domain names global hzSet<hzEmaddr> _hzGlobal_setEmaddrs ; // Repository of email addresses
global hzSSR g_ssrInet ; // Small string regime reserved for hzEmaddr, hzDomain and hzUrl
/* ** Definitions */
struct _ema_space { // Internal structure for email address stringspace. Note there is no constructor as string spaces are allocated by Alloc() from superblocks.
uchar m_copy ; // Copy counter uchar m_lhs ; // Length left of the '@' uchar m_rhs ; // Length right of the '@' char m_data[5] ; // First part of data } ;
#define EMA_FACTOR 4 // This is added to the email string size to accomodate the copy count and the size of the strings to the left and right of the @, // the @ itself and the null terminator.
/* ** Global constants */
global const hzEmaddr _hz_null_hzEmaddr ; // Null email address
/* ** hzEmaddr public methods */
void hzEmaddr::Clear (void) { // Clear the contents // // Arguments: None // Returns: None
_hzfunc("hzEmaddr::Clear") ;
_ema_space* pCtrl ; // This email address space uint32_t nLen ; // Length hzEcode rc = E_OK ; // Return code
if (m_addr) { pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) hzexit(E_CORRUPT, "Illegal string address %u:%u", (m_addr&0x7fff0000)>>16, m_addr&0xffff) ;
if (pCtrl->m_copy == 0) { threadLog("Deletion in progress address %u:%u\n", (m_addr&0x7fff0000)>>16, m_addr&0xffff) ; m_addr = 0 ; return ; }
if (pCtrl->m_copy == 0xff) { //hzerr(E_CORRUPT, "Invalid email addr (cpy %u lhs %u rhs %u) address %u:%u", pCtrl->m_copy, pCtrl->m_lhs, pCtrl->m_rhs, (m_addr&0x7fff0000)>>16, m_addr&0xffff) ; threadLog("CORRUPT: Invalid email addr (cpy %u lhs %u rhs %u) address %u:%u\n", pCtrl->m_copy, pCtrl->m_lhs, pCtrl->m_rhs, (m_addr&0x7fff0000)>>16, m_addr&0xffff) ; m_addr = 0 ; return ; }
if (pCtrl->m_copy && pCtrl->m_copy < 100) { if (_hzGlobal_MT) __sync_add_and_fetch(&(pCtrl->m_copy), -1) ; else pCtrl->m_copy-- ;
if (pCtrl->m_copy == 0) { // threadLog("Freeing emaddr (cpy %u lhs %u rhs %u) address %u:%u [%s]\n", // pCtrl->m_copy, pCtrl->m_lhs, pCtrl->m_rhs, (m_addr&0x7fff0000)>>16, m_addr&0xffff, pCtrl->m_data) ;
//pCtrl->m_copy = 0xff ; nLen = pCtrl->m_lhs + pCtrl->m_rhs + 1 ; rc = g_ssrInet.Free(m_addr, nLen + EMA_FACTOR) ; } }
m_addr = 0 ; }
if (rc != E_OK) threadLog("Email address %s not deleted\n", pCtrl->m_data) ; }
uint32_t hzEmaddr::Length (void) const { // Return length in bytes of the whole email address
_hzfunc("hzEmaddr::Length") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_lhs + pCtrl->m_rhs + 1 ; }
uint32_t hzEmaddr::Copies (void) const { // Return number of copies for diagnostics
_hzfunc("hzEmaddr::Copies") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_copy ; }
bool hzEmaddr::_inc_copy (void) const { _ema_space* pCtrl ; // This string's control area
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("_inc_copy - invalid address %u:%u\n", (m_addr&0xffff0000)>>16, (m_addr&0xffff)) ; return false ; }
if (pCtrl->m_copy == 0xff) { threadLog("_inc_copy - item deleted (%u:%u)\n", (m_addr&0xffff0000)>>16, (m_addr&0xffff)) ; return false ; }
if (pCtrl->m_copy < 100) pCtrl->m_copy++ ; return true ; }
void hzEmaddr::_dec_copy (void) const { _ema_space* pCtrl ; // This string's control area
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
if (pCtrl->m_copy == 1) threadLog("WARNING: EMA _dec_copy would zero copy count\n") ; else pCtrl->m_copy-- ; }
bool hzEmaddr::valid (void) const { _ema_space* pCtrl ; // This string's control area _ssrFLE* pSlot ; // Item cast to _ssrFLE (to self point on free and to check it is not already free)
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; pSlot = (_ssrFLE*) pCtrl ;
if (!pCtrl->m_copy || pCtrl->m_copy == 0xff) return false ; return true ; }
uint32_t hzEmaddr::LhsLen (void) const { // Return length in bytes of the first part email address
_hzfunc("hzEmaddr::LhsLen") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_lhs ; }
uint32_t hzEmaddr::DomLen (void) const { // Return length in bytes of the domain part of the email address
_hzfunc("hzEmaddr::DomLen") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_rhs ; }
const char* hzEmaddr::GetDomain (void) const { // Return domain name as null terminated string
_hzfunc("hzEmaddr::GetDomain") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_data + pCtrl->m_lhs + 1 ; }
const char* hzEmaddr::GetAddress (void) const { // Return whole email address as null terminated string
_hzfunc("hzEmaddr::GetAddress") ;
_ema_space* pCtrl ; // This email address space
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; if (!pCtrl) { threadLog("Ivalid string space %u:%u\n", (m_addr&0x7fff000)>>16, m_addr&0xffff) ; return 0 ; }
return pCtrl->m_data ; }
hzEmaddr& hzEmaddr::operator= (const char* cpStr) { // Assign the hzEmaddr to an email address held in a character string // // Argument: cpStr A null terminated string assumed to be an email address // // Returns: Reference to this email adress instance in all cases. // // Note: This function will record an E_FORMAT error if the supplied cstr did not amount to an email address
_hzfunc("hzEmaddr::operator=(cstr)") ;
_ema_space* destCtl ; // This email address space const char* i ; // Email iterator char* j ; // Email iterator uint32_t nLhs = 0 ; // LHS part of email address uint32_t nRhs = 0 ; // RHS part of email address
Clear() ;
if (!cpStr || !cpStr[0]) return *this ;
if (!IsEmaddr(cpStr)) { hzerr(E_FORMAT, "Cannot assign %s", cpStr) ; return *this ; }
for (i = cpStr ; *i && *i != '@' ; nLhs++, i++) ; if (*i == '@') for (i++ ; *i ; nRhs++, i++) ;
if (nLhs < 1 || nLhs > 192 || nRhs < 1 || nRhs > 63) { hzerr(E_FORMAT, "Cannot assign %s", cpStr) ; return *this ; }
m_addr = g_ssrInet.Alloc(nLhs + nRhs + 1 + EMA_FACTOR) ; if (!m_addr) hzexit(E_MEMORY, "Cannot assign %s", cpStr) ; destCtl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
// Assign the value destCtl->m_copy = 1 ; destCtl->m_lhs = nLhs & 0xff ; destCtl->m_rhs = nRhs & 0xff ; for (j = destCtl->m_data, i = cpStr ; *i ; *j++ = _tolower(*i++)) ; *j = 0 ; return *this ; }
hzEmaddr& hzEmaddr::operator= (const hzString& S) { // Assign the hzEmaddr to an email address held in a hzString instance // // Argument: S A string assumed to be an email address // // Returns: Reference to this email adress instance in all cases. // // Note: This function will record an E_FORMAT error if the supplied cstr did not amount to an email address
_hzfunc("hzEmaddr::operator=(hzStr)") ;
Clear() ; return operator=(*S) ; }
hzEmaddr& hzEmaddr::operator= (const hzChain::Iter& ci) { // Determines if the supplied iterator is at the start of a valid email address and if it is, assignes this as the value to the calling instance. // // Argument: ci Chain iterator // // Returns: Reference to this email address instance. This will be empty if the input did not amount to an email address
_hzfunc("hzEmaddr::operator=(chIter)") ;
hzChain::Iter xi ; // External chain iterator
_ema_space* pCtrl ; // This email address space char* i ; // For populating string int32_t at = 0 ; // The @ has been encountered (later used as a counter) uchar nLhs = 0 ; // Chars before the @ uchar nRhs = 0 ; // Chars after the @ uchar nPeriod = 0 ; // No of periods on RHS char lCh = 0 ; // Last char processed
Clear() ; if (ci.eof()) return *this ;
// Process the string and set char incidence aggregates for (xi = ci ; !xi.eof() && *xi > CHAR_SPACE ; lCh = *xi, xi++) { if (*xi == CHAR_AT) { if (at) return *this ; if (!lCh || lCh == CHAR_PERIOD) return *this ; at = 1 ; continue ; }
if (*xi == CHAR_PERIOD) { if (!lCh || lCh == CHAR_PERIOD || lCh == CHAR_AT) return *this ; if (at) { nRhs++ ; nPeriod++ ; } else nLhs++ ; continue ; }
if (at) { if (IsUrlnorm(*xi)) { nRhs++ ; if (nRhs > 63) return *this ; continue ; } } else { if (IsUrlnorm(*xi) || *xi=='!' || *xi=='#' || *xi=='$' || *xi=='%' || *xi=='&' || *xi=='\'' || *xi=='*' || *xi=='+' || *xi=='/' || *xi=='=' || *xi=='?' || *xi=='^' || *xi=='`' || *xi=='{' || *xi=='|' || *xi=='}' || *xi=='~' || *xi=='.') { nLhs++ ; if (nLhs > 192) return *this ; continue ; } }
break ; }
if (lCh == CHAR_PERIOD || !at || !nPeriod || !nLhs || nRhs < 2) { hzerr(E_FORMAT, "Cannot assign") ; return *this ; }
if (lCh == CHAR_PERIOD) return *this ; if (!at) return *this ; if (!nPeriod) return *this ; if (!nLhs || nRhs < 2) return *this ;
//m_cpBuf = new uchar[nLhs + nRhs + 5] ; m_addr = g_ssrInet.Alloc(nLhs + nRhs + 1 + EMA_FACTOR) ; if (!m_addr) hzexit(E_MEMORY, "Cannot assign %d bytes", nLhs + nRhs + 5) ; pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
i = (char*) pCtrl->m_data ;
for (xi = ci, at = 0 ; at < (nLhs + nRhs + 1) ; at++, xi++) i[at] = _tolower(*xi) ; i[at] = 0 ;
pCtrl->m_copy = 1 ; pCtrl->m_lhs = nLhs ; pCtrl->m_rhs = nRhs ;
return *this ; }
hzEmaddr& hzEmaddr::operator= (const hzEmaddr& E) { // Assign the hzEmaddr to an email address held in another hzEmaddr instance // // Arguments: 1) E The supplied email address as a hzEmail instance // // Returns: Reference to this hzEmail instance
// It this internal pointer and that of the operand already point to the same space in memory, do nothing
_hzfunc("hzEmaddr::operator=") ;
_ema_space* pSupp ; // Supplied email address space
if (m_addr == E.m_addr) return *this ;
Clear() ;
if (E.m_addr) { // Increment copy count pSupp = (_ema_space*) g_ssrInet.Xlate(E.m_addr) ; if (!pSupp) { threadLog("Invalid src emaddr - addr is %u:%u\n", (E.m_addr & 0xffff0000) >> 16, E.m_addr & 0xffff) ; return *this ; }
if (pSupp->m_copy == 0xff) { threadLog("Trying to assign to a deleted emaddr <%s>\n", pSupp->m_data) ; m_addr = 0 ; return *this ; }
if (pSupp->m_copy < 100) { if (_hzGlobal_MT) //__sync_add_and_fetch(&(suppCtl->m_copy), 1) ; pSupp->m_copy++ ; else pSupp->m_copy++ ; }
m_addr = E.m_addr ; }
return *this ; }
/* ** Compare operators */
static int32_t _lhscompare (const char* a, const char* b) { // Compare only upto the @ in what is assumend to be two email addresses // // Arguments: 1) a First email address // 2) b Second email address // // Returns: -1 If the LHS of a < LHS of b // +1 If the LHS of a > LHS of b // 0 If the LHS of a = LSH of b
_hzfunc(__func__) ;
for (; *a && *a != '@' && *a == *b ; a++, b++) ;
if (*a == '@' || *a == 0) { if (*b == '@' || *b == 0) return 0 ; return -1 ; }
if (*b == '@' || *b == 0) return 1 ;
return *a > *b ? 1 : -1 ; }
bool hzEmaddr::operator== (const hzEmaddr& E) const { // Test for equality between this hzEmaddr and an operand instance // // Arguments: 1) E Test email address // // Returns: True If this addesss is equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator==") ;
_ema_space* pCtrl ; // This email address space _ema_space* suppCtl ; // Supplied email address space int32_t res ; // Comparison result
if (m_addr == E.m_addr) return true ; if (m_addr && E.m_addr == 0) return false ; if (E.m_addr && m_addr == 0) return false ;
// Compare domains first then LHS pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; suppCtl = (_ema_space*) g_ssrInet.Xlate(E.m_addr) ;
// Compare domains res = strcmp(pCtrl->m_data + pCtrl->m_lhs + 1, suppCtl->m_data + suppCtl->m_lhs + 1) ; if (res) return false ;
// Compare LHS res = _lhscompare((char*) pCtrl->m_data, (char*) suppCtl->m_data) ; if (res) return true ; return false ; }
bool hzEmaddr::operator< (const hzEmaddr& E) const { // Return true if this hzEmaddr instance is lexically less than the operand. Note that comparison is first done on the domain part (the RHS // of the @) and then done on the address part (the LHS of the @) // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically less than the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator<") ;
int32_t res ; // Comparison result
// Are this and the operand connected? if (m_addr == E.m_addr) return false ; if (m_addr && E.m_addr == 0) return false ; if (E.m_addr && m_addr == 0) return true ;
// Compare domains first res = strcmp(GetDomain(), E.GetDomain()) ; if (res < 0) return true ; if (res > 0) return false ;
// Domains are equal so compare LHS res = _lhscompare(GetAddress(), *E) ; return res < 0 ? true : false ; }
bool hzEmaddr::operator<= (const hzEmaddr& E) const { // Return true if this hzEmaddr instance is lexically less than or equal to the operand. Note that comparison is first done on the domain // part (the RHS of the @) and then done on the address part (the LHS of the @) // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically less than or equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator<=") ;
int32_t res ; // Comparison result
// Are this and the operand connected? if (m_addr == E.m_addr) return true ; if (m_addr && E.m_addr == 0) return false ; if (E.m_addr && m_addr == 0) return true ;
// Compare domains first res = strcmp(GetDomain(), E.GetDomain()) ; if (res < 0) return true ; if (res > 0) return false ;
// Domains are equal so compare LHS res = _lhscompare(GetAddress(), E) ; return res <= 0 ? true : false ; }
bool hzEmaddr::operator> (const hzEmaddr& E) const { // Return true if this hzEmaddr instance is lexically greater than the operand. Note that comparison is first done on the domain // part (the RHS of the @) and then done on the address part (the LHS of the @) // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically greater than the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator>") ;
int32_t res ; // Comparison result
// Are this and the operand connected? if (m_addr == E.m_addr) return false ; if (m_addr && E.m_addr == 0) return true ; if (E.m_addr && m_addr == 0) return false ;
// Compare domains first res = strcmp(GetDomain(), E.GetDomain()) ; if (res > 0) return true ; if (res < 0) return false ;
// Domains are equal so compare LHS res = _lhscompare(GetAddress(), E) ; return res > 0 ? true : false ; }
bool hzEmaddr::operator>= (const hzEmaddr& E) const { // Return true if this hzEmaddr instance is lexically greater than or equal to the operand. Note that comparison is first done on the domain // part (the RHS of the @) and then done on the address part (the LHS of the @) // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically greater than or equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator>=") ;
int32_t res ; // Comparison result
// Are this and the operand connected? if (m_addr == E.m_addr) return true ; if (m_addr && E.m_addr == 0) return true ; if (E.m_addr && m_addr == 0) return false ;
// Compare domains first res = strcmp(GetDomain(), E.GetDomain()) ; if (res > 0) return true ; if (res < 0) return false ;
// Domains are equal so compare LHS res = _lhscompare(GetAddress(), E) ; return res >= 0 ? true : false ; }
bool hzEmaddr::operator== (const hzString& S) const { // Test for equality between this hzEmaddr and an email address held in a hzString // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator==") ;
_ema_space* pCtrl ; // This email address space
if (!S && !m_addr) return true ; if (!S) return false ; if (!m_addr) return false ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
return CstrCompare((char*) pCtrl->m_data, *S) == 0 ? true : false ; }
bool hzEmaddr::operator!= (const hzString& S) const { // Test for inequality between this hzEmaddr and an email address held in a hzString // // Arguments: 1) E Test email address // // Returns: True If this addesss is not lexically equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator!=") ;
_ema_space* pCtrl ; // This email address space
if (!S && !m_addr) return false ; if (!S) return true ; if (!m_addr) return true ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
return CstrCompare((char*) pCtrl->m_data, *S) == 0 ? false : true ; }
bool hzEmaddr::operator== (const char* cpStr) const { // Test for equality between this hzEmaddr and an email address held in a character string // // Arguments: 1) E Test email address // // Returns: True If this addesss is lexically equal to the supplied test email address // False Otherwise
_hzfunc("hzEmaddr::operator==") ;
_ema_space* pCtrl ; // This email address space
if ((!cpStr || !cpStr[0]) && !m_addr) return true ; if (!cpStr || !cpStr[0]) return false ; if (!m_addr) return false ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
return CstrCompare((char*) pCtrl->m_data, cpStr) == 0 ? true : false ; }
bool hzEmaddr::operator!= (const char* cpStr) const { // Test for inequality between this hzEmaddr and an email address held in a character string // // Arguments: 1) E Test email address // // Returns: True If this email addesss is not lexically equal to the supplied // False If this email address has the same value as the supplied
_hzfunc("hzEmaddr::operator!=") ;
_ema_space* pCtrl ; // This email address space
if ((!cpStr || !cpStr[0]) && !m_addr) return false ; if (!cpStr || !cpStr[0]) return true ; if (!m_addr) return true ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ;
return CstrCompare((char*) pCtrl->m_data, cpStr) == 0 ? false:true ; }
const char* hzEmaddr::operator* (void) const { // Returns the URL data (a null terminated string) // // Arguments: None // Returns: Content as null terminated string
_hzfunc("hzEmaddr::operator*") ;
_ema_space* pCtrl ; // This string's control area
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; return pCtrl->m_data ; }
hzEmaddr::operator const char* (void) const { // Returns the string data (a null terminated string) // // Arguments: None // Returns: Content as null terminated string
_hzfunc("hzEmaddr::operator const char*") ;
_ema_space* pCtrl ; // This string's control area
if (!m_addr) return 0 ;
pCtrl = (_ema_space*) g_ssrInet.Xlate(m_addr) ; return pCtrl->m_data ; }
/* ** Stream operator */
std::ostream& operator<< (std::ostream& os, const hzEmaddr& obj) { // Category: Data Output // // Friend function to hzEmaddr class to stream out the email address. // // Arguments: 1) os Reference to output stream // 2) ema Const reference to an email address // // Returns: Reference to the supplied output stream
_hzfunc("operator<<(ostream,hzEmaddr)") ;
os << *obj ; return os ; }
bool IsEmaddr (const char* cpStr) { // Category: Text Processing // // Tests if a supplied string (or text at a hzChain iterator) is of the form of an email address. To qualify, there must be a single occurence // of '@' both preceeded and followed by strings of non-zero length whose characters are members of a set of permitted characters (see below). // There also must be at least one period in the string following the @. Additionally the length of the whole must not exceed 255. // // The first instance of a whitespace character (<= space) terminates the test. If the string up to but not including the whitespace character // or null terminator, then the test is passed, otherwise it fails. // // Permitted chars on the LHS of the '@' are: [a-z], [A-Z], [0-9], [!, #, $, %, &, ', *, +, -, /, =, ?, ^, _, `, {, |, }, ~] and the period (.) // if it is not the last character in the string. // // Permitted chars on the LHS of the '@' are: [a-z], [A-Z], [0-9] and the period (.) or minus sign (-) if they are not the last character in the // string. // // Arguments: 1) cpStr The char pointer to be tested // // Returns: True If the supplied cstr sets the email address // False Otherwise
_hzfunc("IsEmaddr") ;
const char* i ; // Source string iterator uint32_t nLhs = 0 ; // Count to the left of the @ uint32_t nRhs = 0 ; // Count to the right of the @ bool bPeriod = false ; // Confirmed period
if (!cpStr || !cpStr[0]) return false ;
// Count chars upto the @ for (i = cpStr ; *i > CHAR_SPACE ; i++) { if (*i == CHAR_AT) break ;
if ((*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z') || (*i >= '0' && *i <= '9') || *i=='!' || *i=='#' || *i=='$' || *i=='%' || *i=='&' || *i=='\'' || *i=='*' || *i=='+' || *i=='-' || *i=='/' || *i=='=' || *i=='?' || *i=='^' || *i=='_' || *i=='`' || *i=='{' || *i=='|' || *i=='}' || *i=='~' || (*i=='.' && i[1] > ' ' && i[1] != '@' && nLhs)) { nLhs++ ; if (nLhs > 63) return false ; continue ; }
break ; }
if (*i != CHAR_AT || !nLhs) return false ;
// Count chars beyond @ for (i++ ; *i > CHAR_SPACE ; i++) { if (*i == CHAR_AT) return false ;
if (*i == CHAR_PERIOD && i[1] && i[1] != CHAR_PERIOD) { bPeriod = true ; continue ; }
if ((*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z') || (*i >= '0' && *i <= '9') || (*i=='-' && i[1] > ' ' && nRhs) || (*i=='.' && i[1] > ' ' && nRhs)) { nRhs++ ; if (nRhs > 192) return false ; continue ; }
break ; }
if (bPeriod && nLhs && nRhs > 2) return true ; return false ; }
bool AtEmaddr (hzEmaddr& ema, uint32_t& nLen, hzChain::Iter& ci) { // Category: Text Processing // // If the supplied iterator is at the start of a valid email address, then the supplied email address instance will be populated with this // address as the value and the supplied length will be set. // // Arguments: 1) ema Reference to an email address, populated by this function // 2) nLen Reference to an integer set to the email length // 3) ci Input chain iterator // // Returns: True If the supplied cstr sets the email address // False Otherwise
_hzfunc("AtEmaddr") ;
ema.Clear() ; ema = ci ; if (!ema) return false ; nLen = ema.Length() ; return true ; }
/* ** Diagnostics */
hzEcode IntegEmaddrSet (bool bVerbose) { // Runs through the _hzGlobal_setEmaddrs, looking for invalid entires
_hzfunc(__func__) ;
hzLogger* pLog ; // Log file _ema_space* pCtrl ; // This string's control area //_ssrFLE* pSlot ; // Item cast to _ssrFLE (to self point on free and to check it is not already free) hzEmaddr ema ; // Email address uint32_t n ; // Iterator uint32_t addr ; // Internal address uint32_t nFail ; // Number of invalid addresses uint32_t nPass ; // Number of invalid addresses
pLog = GetThreadLogger() ;
for (n = nPass = nFail = 0 ; n < _hzGlobal_setEmaddrs.Count() ; n++) { ema = _hzGlobal_setEmaddrs.GetObj(n) ;
addr = ema._int_addr() ; if (!addr) { nFail++ ; continue ; }
pCtrl = (_ema_space*) g_ssrInet.Xlate(addr) ; //pSlot = (_ssrFLE*) pCtrl ;
if (!pCtrl->m_copy || pCtrl->m_copy == 0xff || !pCtrl->m_lhs || !pCtrl->m_rhs) nFail++ ; else { if (bVerbose) pLog->Out("%u:%u: copy %u -> %s\n", (addr&0xffff0000) >> 16, addr&0xffff, pCtrl->m_copy, pCtrl->m_data) ; nPass++ ; } }
pLog->Log("Total email population %u. No OK %u Failed %u\n", _hzGlobal_setEmaddrs.Count(), nPass, nFail) ; return E_OK ; }
void InetIntegrityReport (hzChain& report) { _hzfunc(__func__) ;
g_ssrInet.Report(report) ; }