// // File: hzTmplMapS.h // // 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. //
#ifndef hzTmplMapS_h #define hzTmplMapS_h
#include <sys/stat.h>
#include "hzProcess.h" #include "hzString.h" #include "hzLock.h" #include "hzIsamT.h"
/* ** The formal hzMapS template */
template<class KEY, class OBJ> class hzMapS { // Category: Object Collection // // The hzMapS template provides a memory resident one to one map of keys to objects. The keys are required to be unique and there may only be one // object per key. Both the keys and the objects can be of any C++, HadronZoo or application specific type.
_hz_tmpl_ISAM base ; // _hz_set_isam_Value ordered list by value KEY m_NullKey ; // Null key mutable KEY m_DefaultKey ; // Default key (effectively NULL) OBJ m_NullObj ; // Null key mutable OBJ m_DefaultObj ; // Default key (effectively NULL)
// Prevent copies hzMapS<KEY,OBJ> (const hzMapS<KEY,OBJ>&) ; hzMapS<KEY,OBJ>& operator= (const hzMapS<KEY,OBJ>&) ;
public: hzMapS (void) { base.Start(sizeof(KEY), sizeof(OBJ)) ; base.SetLock(HZ_NOLOCK) ; base.m_compare = _tmpl_map_compare<KEY,OBJ> ; memset(&m_NullKey, 0, sizeof(KEY)) ; memset(&m_NullObj, 0, sizeof(OBJ)) ; _hzGlobal_Memstats.m_numSmaps++ ; }
hzMapS (hzLockOpt eLock) { base.Start(sizeof(KEY), sizeof(OBJ)) ; base.SetLock(eLock) ; base.m_compare = _tmpl_map_compare<KEY,OBJ> ; memset(&m_NullKey, 0, sizeof(KEY)) ; memset(&m_NullObj, 0, sizeof(OBJ)) ; _hzGlobal_Memstats.m_numSmaps++ ; }
hzMapS (const hzString& name) { base.Start(sizeof(KEY), sizeof(OBJ)) ; base.SetLock(HZ_NOLOCK) ; base.SetName(name) ; base.m_compare = _tmpl_map_compare<KEY,OBJ> ; memset(&m_NullKey, 0, sizeof(KEY)) ; memset(&m_NullObj, 0, sizeof(OBJ)) ; _hzGlobal_Memstats.m_numSmaps++ ; }
hzMapS (hzLockOpt eLock, const hzString& name) { base.Start(sizeof(KEY), sizeof(OBJ)) ; base.SetLock(eLock) ; base.SetName(name) ; base.m_compare = _tmpl_map_compare<KEY,OBJ> ; memset(&m_NullKey, 0, sizeof(KEY)) ; memset(&m_NullObj, 0, sizeof(OBJ)) ; _hzGlobal_Memstats.m_numSmaps++ ; }
~hzMapS (void) { _hzGlobal_Memstats.m_numSmaps-- ; }
// Init functions void SetLock (hzLockOpt eLock) { base.SetLock(eLock) ; } void SetName (const hzString& name) { base.SetName(name) ; } void Clear (void) { base.Clear() ; }
// Insert and delete by key hzEcode Insert (const KEY& key, const OBJ& obj) { // _hzfunc("hzMapS::Insert") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base.InsertKeyU(nSlot, &key) ; if (pDN) { pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ; pBuck->m_Keys[nSlot] = key ; pBuck->m_Objs[nSlot] = obj ;
return E_OK ; }
return hzerr(E_CORRUPT, "Failed to Insert") ; }
hzEcode Delete (const KEY& key) { // _hzfunc("hzMapS::Delete") ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base._findDnodeByKey(nSlot, &key, HZ_ISAMSRCH_LO) ; if (!pDN) return E_NOTFOUND ;
pDN = base.DeleteKey(nSlot, &key) ; return E_OK ; }
// Locate keys or objects by position OBJ& GetObj (uint32_t nIndex) const { // _hzfunc("hzMapS::GetObj") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base._findDnodeByPos(nSlot, nIndex, false) ; if (!pDN) { m_DefaultObj = m_NullObj ; return m_DefaultObj ; }
pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ; return pBuck->m_Objs[nSlot] ; }
KEY& GetKey (uint32_t nIndex) const { // _hzfunc("hzMapS::GetKey") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base._findDnodeByPos(nSlot, nIndex, false) ; if (!pDN) { m_DefaultKey = m_NullKey ; return m_DefaultKey ; }
pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ; return pBuck->m_Keys[nSlot] ; }
// Locate elements by value bool Exists (const KEY& key) const { // _hzfunc("hzMapS::Exists") ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base._findDnodeByKey(nSlot, &key, HZ_ISAMSRCH_LO) ; if (!pDN) return false ; return true ; }
OBJ& operator[] (const KEY& key) const { //_hzfunc("hzMapS::operator[]") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ; int32_t nSlot ;
pDN = base._findDnodeByKey(nSlot, &key, HZ_ISAMSRCH_LO) ; if (!pDN) { m_DefaultObj = m_NullObj ; return m_DefaultObj ; }
pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ; return pBuck->m_Objs[nSlot] ; }
int32_t First (const KEY key) const { // _hzfunc("hzMapS::First") ;
uint32_t nPosn ; int32_t nSlot ;
if (base._findAllByKey(nSlot, nPosn, key, HZ_ISAMSRCH_LO)) return 0x7fffffff & nPosn ; return -1 ; }
int32_t Last (const KEY key) const { // _hzfunc("hzMapS::Last") ;
uint32_t nPosn ; int32_t nSlot ;
if (base._findAllByKey(nSlot, nPosn, key, HZ_ISAMSRCH_HI)) return 0x7fffffff & nPosn ; return -1 ; }
int32_t Target (const KEY key) const { // _hzfunc("hzMapS::Target") ;
uint32_t nPosn ; int32_t nSlot ;
if (base._findAllByKey(nSlot, nPosn, key, HZ_ISAMSRCH_END)) return 0x7fffffff & nPosn ; return -1 ; }
// Diagnostics uint32_t Nodes (void) const { return base.Nodes() ; } uint32_t Count (void) const { return base.Count() ; } hzEcode NodeErrors (void) const { return base.NodeReport(true) ; } hzEcode NodeReport (void) const { return base.NodeReport(false) ; } } ;
template<class KEY, class OBJ> class hzPMapS { // Category: Object Collection // // Persistent 1:1 map. This is a Serial Datacron implimented as a memory resident 1:1 map, plus delta file. // // Note that classes represented by KEY and OBJ must have serialization functions. Specifically they must have a >> ifstream operator, and either a << ostream operator or an // operator const char*. // // Note that unlike hzMapS, the classes represented by KEY and OBJ must have serialization functions.
hzMapS<KEY,OBJ> m_map ; // The map std::ofstream m_os ; // Delta file hzString m_path ; // Delta file path bool m_bOpen ; // Is delta file open for writing
// Prevent copies hzPMapS<KEY,OBJ> (const hzPMapS<KEY,OBJ>&) ; hzPMapS<KEY,OBJ>& operator= (const hzPMapS<KEY,OBJ>&) ;
public: hzPMapS (void) { m_map.SetLock(HZ_NOLOCK) ; m_bOpen = false ; }
hzPMapS (hzLockOpt eLock) { m_map.SetLock(eLock) ; m_bOpen = false ; }
hzPMapS (const hzString& name) { m_map.SetLock(HZ_NOLOCK) ; m_map.SetName(name) ; m_bOpen = false ; }
hzPMapS (hzLockOpt eLock, const hzString& name) { m_map.SetLock(eLock) ; m_map.SetName(name) ; m_bOpen = false ; }
~hzPMapS (void) { _hzGlobal_Memstats.m_numSmaps-- ; }
// Init functions void SetName (const hzString& name) { m_map.SetName(name) ; } void DeltaSet (const hzString& path) { m_path = path ; }
void DeltaOpen (void) { std::ifstream is ; // Delta file for input struct stat fs ; // File status KEY key ; // Key OBJ obj ; // Object
//rc = OpenInputStrm(is, *m_path) ;
if (lstat(*m_path, &fs) == 0) { if (fs.st_size) { is.open(*m_path) ;
for (; is.tellg() < fs.st_size ;) { is >> key ; if (is.fail()) is.clear() ;
if (is.tellg() == fs.st_size) break ;
is >> obj ; if (is.fail()) is.clear() ;
if (is.tellg() == fs.st_size) threadLog("B: At EOF\n") ;
if (!key) continue ; if (!obj) continue ;
m_map.Insert(key, obj) ; } is.close() ; } }
m_bOpen = true ; m_os.open(*m_path, std::ios::app) ; }
void DeltaClose (void) { m_os.close() ; } void Clear (void) { m_map.Clear() ; }
// Insert and delete by key hzEcode Insert (const KEY& key, const OBJ& obj) { hzEcode rc ; // Return code
if (!m_bOpen) return E_WRITEFAIL ;
rc = m_map.Insert(key, obj) ; if (rc == E_OK) { m_os << key << "\n" ; m_os << obj << "\n" ; m_os.flush() ; } return rc ; }
hzEcode Delete (const KEY& key) { hzEcode rc ; // Return code
if (!m_bOpen) return E_WRITEFAIL ;
rc = m_map.Delete(key) ; m_os << key << "\n" ; m_os << "0\n" ; m_os.flush() ; return rc ; }
// Locate keys or objects by position OBJ& GetObj (uint32_t nIndex) const { return m_map.GetObj(nIndex) ; } KEY& GetKey (uint32_t nIndex) const { return m_map.GetKey(nIndex) ; }
// Locate elements by value bool Exists (const KEY& key) const { return m_map.Exists(key) ; }
OBJ& operator[] (const KEY& key) const { return m_map.operator[](key) ; }
int32_t First (const KEY key) const { return m_map.First(key) ; } int32_t Last (const KEY key) const { return m_map.Last(key) ; } int32_t Target (const KEY key) const { return m_map.Target(key) ; }
// Diagnostics uint32_t Nodes (void) const { return m_map.Nodes() ; } uint32_t Count (void) const { return m_map.Count() ; } hzEcode NodeErrors (void) const { return m_map.NodeReport(true) ; } hzEcode NodeReport (void) const { return m_map.NodeReport(false) ; } } ;
#endif // hzTmplMapS_h