//
// File: hzAtom.cpp
//
// 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 <fstream>
#include <pthread.h>
#include "hzTextproc.h"
#include "hzChars.h"
#include "hzCodec.h"
#include "hzDatabase.h"
using namespace std ;
/*
** Functions to read atom values
*/
static hzString s_cpp_undef = "CPP_UNDEF" ;
static hzString s_hzo_undef = "HZO_UNDEF" ;
static hzString s_bool_true = "TRUE" ;
static hzString s_bool_false = "FALSE" ;
static hzString s_atom_error = "Atom in Error" ;
static hzString s_atom_state = "Atom Unknown Status" ;
const char* hzAtom::Show (void) const
{
// Purpose: Formulate a textual representation of the atom value
//
// Arguments: 1) eFmt Format (optional)
//
// Returns: Instance of hzString by value being atom value in text form.
_hzfunc("hzAtom::Show") ;
const char* ptr ; // From string-like entities
char* pBuf ; // Scratch pad buffer
hzMD5* pMd5 ; // Digest
hzXDate xd ; // Recepticle for hzXDate data
hzDomain dom ; // Domain
hzEmaddr ema ; // Recepticle for hzEmaddr data
hzUrl url ; // Recepticle for hzUrl data
hzIpaddr ipa ; // Recepticle for hzIpaddr data
hzSDate sd ; // Recepticle for hzSDate data
hzTime ti ; // Recepticle for hzTime data
hzString str ; // Temp str
//threadLog("status %d type %d val %x\n", m_eStatus, m_eType, m_Data.m_uInt64) ;
if (m_eStatus == ATOM_CLEAR) return 0 ;
if (m_eStatus == ATOM_ERROR) return s_atom_error ;
if (m_eStatus != ATOM_SET) return s_atom_state ;
switch (m_eType)
{
case BASETYPE_UNDEF: return 0 ;
case BASETYPE_CPP_UNDEF: return *s_cpp_undef ;
case BASETYPE_DIGEST: pMd5 = (hzMD5*) m_Data.m_pVoid ;
if (pMd5)
return pMd5->Txt() ;
return 0 ;
case BASETYPE_DOUBLE: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%f", m_Data.m_Double) ; return pBuf ;
case BASETYPE_INT64: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%ld", m_Data.m_sInt64) ; return pBuf ;
case BASETYPE_INT32: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%d", m_Data.m_sInt32) ; return pBuf ;
case BASETYPE_INT16: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%d", m_Data.m_sInt16) ; return pBuf ;
case BASETYPE_BYTE: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%d", m_Data.m_sByte) ; return pBuf ;
case BASETYPE_UINT64: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%lu", m_Data.m_uInt64) ; return pBuf ;
case BASETYPE_UINT32: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%u", m_Data.m_uInt32) ; return pBuf ;
case BASETYPE_UINT16: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%u", m_Data.m_uInt16) ; return pBuf ;
case BASETYPE_UBYTE: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%u", m_Data.m_uByte) ; return pBuf ;
case BASETYPE_BOOL: return m_Data.m_Bool ? *s_bool_true : *s_bool_false ;
case BASETYPE_HZO_UNDEF: return *s_hzo_undef ;
case BASETYPE_STRING: str._int_set(m_Data.m_uInt32) ; ptr = (const char*) str ; str._int_clr() ; return ptr ;
case BASETYPE_DOMAIN: dom._int_set(m_Data.m_uInt32) ; ptr = (const char*) dom ; dom._int_clr() ; return ptr ;
case BASETYPE_EMADDR: ema._int_set(m_Data.m_uInt32) ; ptr = (const char*) ema ; ema._int_clr() ; return ptr ;
case BASETYPE_URL: return *Url() ;
case BASETYPE_IPADDR: return *Ipaddr() ;
case BASETYPE_TIME: return *Time() ;
case BASETYPE_SDATE: return *SDate() ;
case BASETYPE_XDATE: xd.SetDate(m_Data.m_uInt64) ;
return xd.Txt() ;
case BASETYPE_TEXT: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "TXT ref=%x", m_Data.m_uInt32) ; return pBuf ;
case BASETYPE_BINARY: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "BIN ref=%x", m_Data.m_uInt32) ; return pBuf ;
case BASETYPE_TXTDOC: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "DOC ref=%x", m_Data.m_uInt32) ; return pBuf ;
case BASETYPE_ENUM: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "%u", m_Data.m_sInt32) ; return pBuf ;
case BASETYPE_APPDEF: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "APP ref=%x", m_Data.m_uInt32) ; return pBuf ;
case BASETYPE_CLASS: pBuf = _thisfn.ScratchPad(24) ; sprintf(pBuf, "OBJ ref=%x", m_Data.m_uInt32) ; return pBuf ;
}
return 0 ;
}
const hzMD5 hzAtom::MD5 (void) const
{
// Retrieve hzMD5 from this atom.
//
// Arguments: None
// Returns: hzMD5 instance by value.
hzMD5* pMd5 ; // Pointer to cast
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_DIGEST)
{
pMd5 = (hzMD5*) &m_Data.m_pVoid ;
return *pMd5 ;
}
return _hz_null_hzMD5 ;
}
const hzChain hzAtom::Chain (void) const
{
// Retrieve hzChain from this atom. This will be populated if the hzAtom has a value and the datatype is BASETYPE_STRING, and will be empty otherwise
//
// Arguments: None
// Returns: hzChain instance by value.
if (m_eStatus == ATOM_SET && (m_eType == BASETYPE_TXTDOC || m_eType == BASETYPE_BINARY))
{
hzChain ret ; // To be returned
hzChain tmp ; // Cast
tmp._int_set(m_Data.m_pVoid) ; ret = tmp ; tmp._int_clr() ; return ret ;
}
return _hz_null_hzChain ;
}
const hzString hzAtom::Str (void) const
{
// Retrieve string from this atom. This will be populated only if the hzAtom has a value, the datatype is BASETYPE_STRING, and the string value was set to an actual hzString
// instance, as opposed to being set to a string held in a string repository.
//
// Arguments: None
// Returns: hzString instance by value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_STRING)
{
hzString tmp ; // Cast
hzString ret ; // To be returned
tmp._int_set(m_Data.m_uInt32) ; ret = tmp ; tmp._int_clr() ; return ret ;
}
return _hzGlobal_nullString ;
}
const char* hzAtom::Cstr (void) const
{
// Retrieve Cstr from this atom. This will be populated if the hzAtom has a value and the datatype is BASETYPE_STRING, regardless of how the string value was set.
//
// Arguments: None
// Returns: Instance of hzEmail by value.
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_STRING)
{
const char* pStr ; // Return string value
hzString tmp ; // Cast
tmp._int_set(m_Data.m_uInt32) ; pStr = *tmp ; tmp._int_clr() ; return pStr ;
}
return 0 ;
}
const hzDomain hzAtom::Domain (void) const
{
// Retrieve domain name from this atom. This will be populated if the hzAtom has a value and the datatype is BASETYPE_DOMAIN and be empty otherwise
//
// Arguments: None
// Returns: hzDomain instance by value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_DOMAIN)
{
hzDomain dom ; // To be returned
hzDomain tmp ; // Cast
tmp._int_set(m_Data.m_uInt32) ; dom = tmp ; tmp._int_clr() ; return dom ;
}
return _hz_null_hzDomain ;
}
const hzEmaddr hzAtom::Emaddr (void) const
{
// Retrieve email address from this atom. This will be populated if the hzAtom has a value and the datatype is BASETYPE_EMADDR and be empty otherwise
//
// Arguments: None
// Returns: hzEmail Instance by value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_EMADDR)
{
hzEmaddr ema ; // To be returned
//hzEmaddr tmp ; // Cast
if (m_Data.m_uInt32)
{
ema._int_set(m_Data.m_uInt32) ;
ema._inc_copy() ;
return ema ;
}
//tmp._int_set(m_Data.m_uInt32) ; ema = tmp ; tmp._int_clr() ; return ema ;
}
return _hz_null_hzEmaddr ;
}
const hzUrl hzAtom::Url (void) const
{
// Retrieve URL from this atom. This will be populated if the hzAtom has a value and the datatype is BASETYPE_EMADDR and be empty otherwise
//
// Arguments: None
// Returns: hzUrl instance of hzUrl by value.
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_URL)
{
hzUrl url ; // To be returned
hzUrl tmp ; // Cast
tmp._int_set(m_Data.m_uInt32) ; url = tmp ; tmp._int_clr() ; return url ;
}
return _hz_null_hzUrl ;
}
const hzXDate hzAtom::XDate (void) const
{
// Arguments: None
// Returns: Instance of hzXDate by value. This will be populated if the hzAtom has a value and the datatype is BASETYPE_XDATE and be empty otherwise.
hzXDate tmp ; // Pointer to cast
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_XDATE)
{
tmp.SetDate(m_Data.m_uInt64) ;
return tmp ;
}
return _hz_null_hzXDate ;
}
const hzSDate hzAtom::SDate (void) const
{
// Arguments: None
// Returns: Instance of hzSDate by value. This will be populated if the hzAtom has a value and the datatype is BASETYPE_SDATE and be empty otherwise.
hzSDate tmp ; // Return value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_SDATE)
{
tmp.SetDate(m_Data.m_uInt32) ;
return tmp ;
}
return _hz_null_hzSDate ;
}
const hzTime hzAtom::Time (void) const
{
// Arguments: None
// Returns: Instance of hzTime by value. This will be populated if the hzAtom has a value and the datatype is BASETYPE_TIME and be empty otherwise.
hzTime tmp ; // Return value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_TIME)
{
tmp.SetTime(m_Data.m_uInt32) ;
return tmp ;
}
return _hz_null_hzTime ;
}
const hzIpaddr hzAtom::Ipaddr (void) const
{
// Arguments: None
// Returns: Instance of hzIpaddr by value. This will be populated if the hzAtom has a value and the datatype is BASETYPE_IPADDR and be empty otherwise.
hzIpaddr tmp ; // Return value
if (m_eStatus == ATOM_SET && m_eType == BASETYPE_IPADDR)
{
tmp = m_Data.m_uInt32 ;
return tmp ;
}
return _hzGlobal_nullIP ;
}
/*
** Functions to set hzAtom Values
*/
hzEcode hzAtom::SetValue (hdbBasetype eType, const hzString& S)
{
// Set the atom to the supplied data type and value.
//
// Arguments: 1) eType The datatype
// 2) s The string that either is or contains the value
//
// Returns: E_TYPE If the anticipated data type is not specified or conflicts with current type
// E_BADVALUE If the supplied string does not represent a valid value for the anticipated data type.
// E_OK If the operation was successful.
_hzfunc("hzAtom::SetValue(hzString)") ;
const char* j ; // For processing string data
uint64_t x ; // Storage for integer data
hzXDate xd ; // Storage for hzXDate data
hzSDate sd ; // Storage for hzSDate data
hzTime ti ; // Storage for hzTime data
hzIpaddr ipa ; // Storage for hzIpaddr data
bool bMinus = false ; // Negation indicator
hzEcode rc = E_BADVALUE ; // Return code
// Clear atom first
Clear() ;
// If no value, just return
if (!S)
return E_OK ;
m_eType = eType ;
/*
** HadronZoo string-like types
*/
if (m_eType == BASETYPE_DIGEST)
{
hzMD5 Md5 ; // Pointer to digest value
Md5 = S ;
if (!Md5.IsNull())
{
m_Data.m_pVoid = new uchar[sizeof(hzMD5)] ;
memcpy(m_Data.m_pVoid, Md5.Value(), sizeof(hzMD5)) ;
m_eStatus = ATOM_SET ;
return E_OK ;
}
m_eType = BASETYPE_UNDEF ;
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_STRING)
{
hzString tmp ;
tmp = S ; m_Data.m_uInt32 = tmp._int_addr() ; tmp._int_clr() ;
m_eType = eType ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
return E_OK ;
}
if (m_eType == BASETYPE_DOMAIN)
{
hzDomain tmp ;
tmp = S ;
if (tmp)
{
m_Data.m_uInt32 = tmp._int_addr() ;
tmp._inc_copy() ;
m_eType = eType ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
return E_OK ;
}
m_eType = BASETYPE_UNDEF ;
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_EMADDR)
{
/*
hzEmaddr* pEma ; // Cast
pEma = (hzEmaddr*) &m_Data ;
*pEma = S ;
if (*pEma)
{
m_eType = eType ;
m_eStatus = ATOM_SET ;
return E_OK ;
}
*/
hzEmaddr tmp ;
tmp = S ;
if (tmp)
{
m_Data.m_uInt32 = tmp._int_addr() ;
tmp._inc_copy() ;
m_eType = eType ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
return E_OK ;
}
m_eType = BASETYPE_UNDEF ;
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_URL)
{
hzUrl tmp ; // Temp URL
tmp = S ;
if (tmp)
{
m_Data.m_uInt32 = tmp._int_addr() ;
//tmp._int_clr() ;
tmp._inc_copy() ;
m_eType = eType ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
return E_OK ;
}
m_eType = BASETYPE_UNDEF ;
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
/*
** HadronZoo types without smart pointers
*/
if (m_eType == BASETYPE_IPADDR)
{
ipa = *S ;
if (ipa)
{ m_eStatus = ATOM_SET ; m_Data.m_uInt32 = (uint32_t) ipa ; return E_OK ; }
return E_BADVALUE ;
}
if (m_eType == BASETYPE_XDATE)
{
rc = xd.SetDateTime(S) ;
if (rc == E_OK && xd.AsVal())
{ m_eStatus = ATOM_SET ; m_Data.m_uInt64 = xd.AsVal() ; return E_OK ; }
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_SDATE)
{
rc = sd.SetDate(S) ;
if (rc == E_OK)
{ m_eStatus = ATOM_SET ; m_Data.m_uInt32 = sd.NoDays() ; return E_OK ; }
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_TIME)
{
rc = ti.SetTime(S) ;
if (rc == E_OK)
{ m_eStatus = ATOM_SET ; m_Data.m_uInt32 = ti.NoSecs() ; return E_OK ; }
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
/*
** Numeric types (no smart pointers)
*/
if (m_eType == BASETYPE_DOUBLE)
{
if (IsDouble(m_Data.m_Double, *S))
{ m_eStatus = ATOM_SET ; return E_OK ; }
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
if (m_eType == BASETYPE_BOOL)
{
if (S == "TRUE" || S == "true" || S == "yes" || S == "y" || S == "1") { m_Data.m_Bool = true ; m_eStatus = ATOM_SET ; return E_OK ; }
if (S == "FALSE" || S == "false" || S == "no" || S == "n" || S == "0") { m_Data.m_Bool = false ; m_eStatus = ATOM_SET ; return E_OK ; }
m_eStatus = ATOM_ERROR ;
return E_BADVALUE ;
}
// Must be number or number equiv
j = *S ;
if (*j == CHAR_MINUS)
{ j++ ; bMinus = true ; }
for (x = 0 ; IsDigit(*j) ; j++)
{ x *= 10 ; x += (*j - '0') ; }
if (*j)
return E_BADVALUE ;
switch (m_eType)
{
case BASETYPE_BYTE: if (x > 0x7f)
return E_BADVALUE ;
m_Data.m_sByte = x & 0x7f ;
if (bMinus)
m_Data.m_sByte *= -1 ;
break ;
case BASETYPE_INT16: if (x > 0x7fff)
return E_BADVALUE ;
m_Data.m_sInt16 = x & 0x7fff ;
if (bMinus)
m_Data.m_sInt16 *= -1 ;
break ;
case BASETYPE_INT32: if (x > 0x7fffffff)
return E_BADVALUE ;
m_Data.m_sInt32 = x & 0x7fffffff ;
if (bMinus)
m_Data.m_sInt32 *= -1 ;
break ;
case BASETYPE_INT64: m_Data.m_sInt64 = x ;
if (bMinus)
m_Data.m_sInt64 *= -1 ;
break ;
case BASETYPE_UBYTE: if (x & 0xffffffffffffff00)
return E_BADVALUE ;
m_Data.m_uByte = (x & 0xff) ;
break ;
//case BASETYPE_ENUM2:
case BASETYPE_UINT16: if (x & 0xffffffffffff0000)
return E_BADVALUE ;
m_Data.m_uInt16 = (x & 0xffff) ;
break ;
case BASETYPE_UINT32: if (x & 0xffffffff00000000)
return E_BADVALUE ;
m_Data.m_uInt32 = (x & 0xffffffff) ;
break ;
//case BASETYPE_UUID:
case BASETYPE_UINT64: m_Data.m_uInt64 = x ;
break ;
}
m_eStatus = ATOM_SET ;
return E_OK ;
}
hzEcode hzAtom::SetValue (hdbBasetype eType, const _atomval& av)
{
// Set the atom to the supplied data type and value (supplied in an _atomval)
//
// Arguments: 1) eType The datatype
// 2) s The string that either is or contains the value
//
// Returns: E_TYPE If the anticipated data type is not specified or conflicts with current type
// E_BADVALUE If the supplied string does not represent a valid value for the anticipated data type.
// E_OK If the operation was successful.
_hzfunc("hzAtom::SetValue(atomval)") ;
// If the current and supplied data type are the same and the current m_Data equal to the supplied _atomval, do nothing
/*
if (m_eType == eType && m_Data.m_uInt64 == av.m_uInt64)
return E_OK ;
*/
// Clear the atom (in all cases)
Clear() ;
if (!av.m_uInt64)
return E_OK ;
m_eType = eType ;
m_Data = av ;
m_eStatus = ATOM_SET ;
return E_OK ;
}
hzEcode hzAtom::SetNumber (const char* s)
{
// Set atom to a numeric data type and value if the supplied string amounts to a numberic value, i.e. is of the form
// [sign] digits [[.] digits] [[e][sign]digits]
//
// Arguments: 1) s The supplied string.
//
// Returns: E_NOINIT If the anticipated data type is not specified.
// E_BADVALUE If the supplied string does not represent a valid value for the anticipated data type.
// E_OK If the operation was successful.
_hzfunc("hzAtom::SetNumber") ;
const char* i ; // Iterator
uint64_t valA ; // For digits past the decimal point
double valD ; // For double value
uint32_t valB ; // For digits past the decimal point
uint32_t valE ; // For digits past the exponent
uint32_t nDigits = 0 ; // Digit counter
int32_t nBytes = 0 ; // Byte count
bool bNeg = false ; // Minus operator indicator
Clear() ;
i = s ;
if (!i)
return E_NODATA ;
// Deal with leading sign
if (*i == CHAR_MINUS)
{ bNeg = true ; i++ ; }
else if (*i == CHAR_PLUS)
i++ ;
else if (i[0] == '0' && (i[1] == 'x' || i[1] == 'X'))
{
// Whole token must be hex and limited to 16 bytes - otherwise fail.
for (i += 2 ; IsHex(*i) ; nBytes++, i++)
{
valA *= 16 ;
if (*i >= '0' && *i <= '9') { valA += (*i - '0') ; continue ; }
if (*i >= 'A' && *i <= 'F') { valA += 10 ; valA += (*i - 'A') ; continue ; }
if (*i >= 'a' && *i <= 'f') { valA += 10 ; valA += (*i - 'a') ; continue ; }
break ;
}
if (*i)
{ m_eType = BASETYPE_UNDEF ; return E_FORMAT ; }
if (!nBytes || nBytes > 16)
{ m_eType = BASETYPE_UNDEF ; return E_FORMAT ; }
if (nBytes > 8) { m_eType = BASETYPE_UINT64 ; m_Data.m_uInt64 = valA ; }
else if (nBytes > 4) { m_eType = BASETYPE_UINT32 ; m_Data.m_uInt32 = valA & 0xffffffff ; }
else if (nBytes > 2) { m_eType = BASETYPE_UINT16 ; m_Data.m_uInt16 = valA & 0xffff ; }
else
{ m_eType = BASETYPE_UBYTE ; m_Data.m_uByte = valA & 0xff ; }
return E_OK ;
}
// Expect a series of at least one digit
for (nDigits = 0 ; IsDigit(*i) ; nBytes++, nDigits++, i++)
{
valA *= 10 ;
if (*i >= '0' && *i <= '9')
{ valA += (*i - '0') ; continue ; }
break ;
}
if (!nDigits)
return BASETYPE_UNDEF ;
// Test for a period that is followed by at least one digit
if (*i == CHAR_PERIOD)
{
i++ ;
for (nDigits = 0 ; IsDigit(*i) ; nBytes++, nDigits++, i++)
{
valD *= 10.0 ;
if (*i >= '0' && *i <= '9')
{ valB += (*i - '0') ; continue ; }
break ;
}
if (!nDigits)
return BASETYPE_UNDEF ;
for (; nBytes ; nBytes--)
valD /= 10.0 ;
valD += (double) valA ;
// Test for the 'e' followed by at least one digit or a +/- followed by at least one digit
if (*i == 'e')
{
i++ ;
if (*i == CHAR_MINUS || *i == CHAR_PLUS)
{ nBytes++ ; i++ ; }
for (nDigits = 0 ; IsDigit(*i) ; nBytes++, nDigits++, i++)
{
valE *= 10 ;
if (*i >= '0' && *i <= '9')
{ valE += (*i - '0') ; continue ; }
break ;
}
if (!nDigits)
return BASETYPE_UNDEF ;
}
m_Data.m_Double = valD ;
m_eType = BASETYPE_DOUBLE ;
return E_OK ;
}
// Not a double
if (nDigits > 8)
{
if (bNeg)
{ m_Data.m_sInt64 = valA ; m_eType = BASETYPE_INT64 ; }
else
{ m_Data.m_uInt64 = valA ; m_eType = BASETYPE_UINT64 ; }
}
else if (nDigits > 4)
{
if (bNeg)
{ m_Data.m_sInt32 = valA ; m_eType = BASETYPE_INT32 ; }
else
{ m_Data.m_uInt32 = valA ; m_eType = BASETYPE_UINT32 ; }
}
else if (nDigits > 2)
{
if (bNeg)
{ m_Data.m_sInt16 = valA ; m_eType = BASETYPE_INT16 ; }
else
{ m_Data.m_uInt16 = valA ; m_eType = BASETYPE_UINT16 ; }
}
else
{
if (bNeg)
{ m_Data.m_sByte = valA ; m_eType = BASETYPE_BYTE ; }
else
{ m_Data.m_uByte = valA ; m_eType = BASETYPE_UBYTE ; }
}
m_eStatus = ATOM_SET ;
return E_OK ;
}
hzAtom& hzAtom::operator= (const hzAtom& op)
{
// Set atom type and value to that of another, operand atom.
//
// Argument: a The operand atom
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzAtom)") ;
Clear() ;
if (op.m_eType == BASETYPE_DIGEST)
{
if (op.m_Data.m_pVoid)
{
m_Data.m_pVoid = new uchar[16] ;
memcpy(m_Data.m_pVoid, op.m_Data.m_pVoid, sizeof(hzMD5)) ;
m_eType = op.m_eType ;
m_eStatus = op.m_eStatus ;
}
return *this ;
}
switch (op.m_eType)
{
case BASETYPE_DOMAIN: operator=(op.Domain()) ; break ;
case BASETYPE_EMADDR: operator=(op.Emaddr()) ; break ;
case BASETYPE_URL: operator=(op.Url()) ; break ;
default:
m_eType = op.m_eType ;
m_eStatus = op.m_eStatus ;
//m_bCast = 0 ;
m_Data = op.m_Data ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzMD5& md5)
{
_hzfunc("hzAtom::operator=(hzMD5)") ;
Clear() ;
if (!md5.IsNull())
{
m_Data.m_pVoid = new uchar[sizeof(hzMD5)] ;
memcpy(m_Data.m_pVoid, &md5, sizeof(hzMD5)) ;
m_eType = BASETYPE_DIGEST ;
m_eStatus = ATOM_SET ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzChain& Z)
{
// Set atom value to a chain.
//
// Argument: Z The data as chain
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzChain)") ;
hzChain tmpCh ; // Temporary chain
Clear() ;
if (Z.Size())
{
tmpCh = Z ;
memcpy(&m_Data, &tmpCh, 8) ;
memset(&tmpCh, 0, 8) ;
m_eType = BASETYPE_BINARY ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzString& S)
{
// Set atom value to a string.
//
// Argument: s The data as string
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzString)") ;
Clear() ;
if (S)
{
S._inc_copy() ;
m_Data.m_uInt32 = S._int_addr() ;
m_eType = BASETYPE_STRING ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzDomain& dom)
{
_hzfunc("hzAtom::operator=(hzDomain)") ;
Clear() ;
if (dom)
{
dom._inc_copy() ;
m_Data.m_uInt32 = dom._int_addr() ;
m_eType = BASETYPE_DOMAIN ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzEmaddr& ema)
{
// Set atom value to an email address.
//
// Argument: ema The data as email address
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzEmaddr)") ;
Clear() ;
if (ema)
{
ema._inc_copy() ;
m_Data.m_uInt32 = ema._int_addr() ;
m_eType = BASETYPE_EMADDR ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzUrl& url)
{
// Set atom value to a URL
//
// Argument: url The data as URL
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzUrl)") ;
Clear() ;
if (url)
{
url._inc_copy() ;
m_Data.m_uInt32 = url._int_addr() ;
m_eType = BASETYPE_URL ;
m_eStatus = ATOM_SET ;
//m_bCast = 1 ;
}
return *this ;
}
hzAtom& hzAtom::operator= (const hzIpaddr& ipa)
{
// Set atom value to an IP address.
//
// Argument: ipa The data as IP address
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzIpaddr)") ;
Clear() ;
if (ipa)
{ memcpy(&m_Data, &ipa, sizeof(hzIpaddr)) ; m_eType = BASETYPE_IPADDR ; m_eStatus = ATOM_SET ; }
return *this ;
}
hzAtom& hzAtom::operator= (const hzXDate& xd)
{
// Set atom value to a full date.
//
// Argument: xd The data as full date & time
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzXDate)") ;
Clear() ;
m_eType = BASETYPE_XDATE ;
m_Data.m_uInt64 = xd.AsVal() ;
if (m_Data.m_uInt64)
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (const hzSDate& sd)
{
// Set atom value to a short date.
//
// Argument: sd The data as short form date
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzSDate)") ;
Clear() ;
m_eType = BASETYPE_SDATE ;
if (!sd)
{ m_Data.m_sInt64 = 0 ; m_eStatus = ATOM_CLEAR ; }
else
{ m_Data.m_uInt32 = sd.NoDays() ; m_eStatus = ATOM_SET ; }
return *this ;
}
hzAtom& hzAtom::operator= (const hzTime& time)
{
// Set atom value to a time. Note that this function will have no effect unless the atom has type of undefined or of
// BASETYPE_TIME
//
// Argument: tim Time of day
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(hzTime)") ;
Clear() ;
m_eType = BASETYPE_TIME ;
if (!time)
{ m_Data.m_sInt64 = 0 ; m_eStatus = ATOM_CLEAR ; }
else
{ m_Data.m_uInt32 = time.NoSecs() ; m_eStatus = ATOM_SET ; }
return *this ;
}
hzAtom& hzAtom::operator= (double val)
{
// If the current atom type is unknown or double, set the value
//
// Argument: val Numeric value (double)
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(double)") ;
Clear() ;
m_eType = BASETYPE_DOUBLE ;
m_Data.m_Double = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (int64_t val)
{
// If the current atom type is unknown or int64_t, set the value
//
// Argument: val Numeric value (int64_t)
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(int64)") ;
Clear() ;
m_eType = BASETYPE_INT64 ;
m_Data.m_sInt64 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (uint64_t val)
{
// If the current atom type is unknown or unt64, set the value
//
// Argument: val Unsigned numeric value (uint64_t)
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(uint64)") ;
Clear() ;
m_eType = BASETYPE_UINT64 ;
m_Data.m_uInt64 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (int32_t val)
{
// If the current atom type is unknown or int32_t, set the value
//
// Argument: val The data as an int32_t
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(int32)") ;
Clear() ;
m_eType = BASETYPE_INT32 ;
m_Data.m_sInt32 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (uint32_t val)
{
// If the current atom type is unknown or uint32_t, set the value
//
// Argument: val The data as an uint32_t
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(uint32)") ;
Clear() ;
m_eType = BASETYPE_UINT32 ;
m_Data.m_uInt32 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (int16_t val)
{
// If the current atom type is unknown or int16_t, set the value
//
// Argument: val The data as an int16_t
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(int16)") ;
Clear() ;
m_eType = BASETYPE_INT16 ;
m_Data.m_sInt16 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (uint16_t val)
{
// If the current atom type is unknown or uint16_t, set the value
//
// Argument: val The data as an uint16_t
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(uint16)") ;
Clear() ;
m_eType = BASETYPE_UINT16 ;
m_Data.m_uInt16 = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (char val)
{
// Set the atom value to the supplied char. The type of the atom will need to be either undefined or one of the numeric types.
//
// Argument: val The data as a single char
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(char)") ;
Clear() ;
m_eType = BASETYPE_BYTE ;
m_Data.m_sByte = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (uchar val)
{
// Set the atom value to the supplied unsigned char. The type of the atom will need to be either undefined or one of the numeric types.
//
// Argument: val The data as a single unsigned char
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(uchar)") ;
Clear() ;
m_eType = BASETYPE_UBYTE ;
m_Data.m_uByte = val ;
m_eStatus = ATOM_SET ;
return *this ;
}
hzAtom& hzAtom::operator= (bool b)
{
// Set the atom value to the supplied boolean. The type of the atom will need to be either undefined or TYPE_BOOL
//
// Argument: b The data as a boolean
// Returns: Reference to this atom
_hzfunc("hzAtom::operator=(bool)") ;
Clear() ;
m_eStatus = ATOM_SET ;
m_eType = BASETYPE_BOOL ;
m_Data.m_Bool = b ;
return *this ;
}
hzAtom& hzAtom::Clear (void)
{
// Clear the atom value to null. Note this does not set the type to undefined.
//
// Arguments: None
// Returns: Reference to this atom
_hzfunc("hzAtom::Clear") ;
// Check atom integrity
if (m_eStatus == ATOM_CLEAR)
{
// Must not have either data type or value
if (m_eType == BASETYPE_UNDEF)
{
if (m_Data.m_uInt64)
hzerr(E_CORRUPT, "Atom status clear, no data type but non-zero value") ;
m_Data.m_uInt64 = 0 ;
m_eStatus = ATOM_CLEAR ;
m_eType = BASETYPE_UNDEF ;
}
else
{
if (m_Data.m_uInt64)
hzerr(E_CORRUPT, "Atom status clear but has data type and value") ;
else
hzerr(E_CORRUPT, "Atom status clear, no value but type %s", Basetype2Txt(m_eType)) ;
m_Data.m_uInt64 = 0 ;
m_eStatus = ATOM_CLEAR ;
m_eType = BASETYPE_UNDEF ;
}
// Atom is clear so just return
return *this ;
}
if (m_eStatus == ATOM_ERROR)
{
// Must not have a type, cast, or a value
if (m_eType != BASETYPE_UNDEF) hzerr(E_CORRUPT, "Atom status error - but with data type %s", Basetype2Txt(m_eType)) ;
if (m_Data.m_uInt64) hzerr(E_CORRUPT, "Atom status error - but with value") ;
m_Data.m_uInt64 = 0 ;
m_eStatus = ATOM_CLEAR ;
m_eType = BASETYPE_UNDEF ;
return *this ;
}
if (m_eStatus == ATOM_SET)
{
// Must have data type. Value could be 0 for numeric data types.
if (m_eType == BASETYPE_UNDEF)
hzexit(E_CORRUPT, "Atom status set but no data type") ;
}
else
{
// Status is unknown
hzexit(E_CORRUPT, "Atom status unknown") ;
}
// To get this far the atom must be set, have data type and a legal value for the type
if (m_eType == BASETYPE_DIGEST)
{
if (m_Data.m_pVoid)
delete [] (uchar*) m_Data.m_pVoid ;
}
//if (m_bCast && m_Data.m_uInt32)
if (m_Data.m_uInt32)
{
if (m_eType == BASETYPE_STRING)
{
hzString tmp ;
tmp._int_set(m_Data.m_uInt32) ;
tmp.Clear() ;
}
if (m_eType == BASETYPE_DOMAIN)
{
hzDomain tmp ;
tmp._int_set(m_Data.m_uInt32) ;
tmp.Clear() ;
}
if (m_eType == BASETYPE_EMADDR)
{
hzEmaddr tmp ;
tmp._int_set(m_Data.m_uInt32) ;
tmp.Clear() ;
}
if (m_eType == BASETYPE_URL)
{
hzUrl tmp ;
tmp._int_set(m_Data.m_uInt32) ;
tmp.Clear() ;
}
}
m_Data.m_uInt64 = 0 ;
m_eType = BASETYPE_UNDEF ;
m_eStatus = ATOM_CLEAR ;
//m_bCast = 0 ;
return *this ;
}
std::ostream& operator<< (std::ostream& os, const hzAtom& obj)
{
// Category: Data Output
//
// Facilitates streaming (printing of value) of any atom.
//
// Arguments: 1) os The output stream
// 2) obj The atom to write out
//
// Returns: Reference to the supplied output stream
_hzfunc("hzAtom::operator<<") ;
switch (obj.Type())
{
case BASETYPE_DOMAIN: os << *obj.Domain() ; break ;
case BASETYPE_EMADDR: os << *obj.Emaddr() ; break ;
case BASETYPE_URL: os << *obj.Url() ; break ;
case BASETYPE_STRING: os << *obj.Str() ; break ;
case BASETYPE_IPADDR: os << *obj.Ipaddr() ; break ;
case BASETYPE_XDATE: os << *obj.XDate() ; break ;
case BASETYPE_SDATE: os << *obj.SDate() ; break ;
case BASETYPE_TIME: os << *obj.Time() ; break ;
case BASETYPE_DOUBLE: os << obj.Double() ; break ;
// Kludge to fix no stream handling of _int64_t
case BASETYPE_INT64: os << FormalNumber(obj.Int64()) ; break ;
case BASETYPE_INT32: os << FormalNumber(obj.Int32()) ; break ;
case BASETYPE_INT16: os << obj.Int16() ; break ;
case BASETYPE_BYTE: os << obj.Byte() ; break ;
case BASETYPE_BOOL: if (obj.Bool())
os << "true" ;
else
os << "false" ;
break ;
case BASETYPE_UNDEF: os << "Unknown type" ;
break ;
}
return os ;
}