//
// 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 hzTmplMapM_h
#define hzTmplMapM_h
#include "hzString.h"
#include "hzLock.h"
#include "hzProcess.h"
#include "hzIsamT.h"
/*
** The hzMapM template
*/
template<class KEY, class OBJ> class hzMapM
{
// Category: Object Collection
//
// The hzMapM template provides a memory resident one to many map of keys (class KEY) to objects (class OBJ). Although there can be many objects
// with the same key the hzMapM template uses the same _hz_map_Pair ISAM as hzMapS - meaning that the key is repeated for each object associated
// with it. Note for any given key, objects are inserted in the order of incidence so the insert location is always one place after the last.
_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
hzMapM<KEY,OBJ> (const hzMapM<KEY,OBJ>&) ;
hzMapM<KEY,OBJ>& operator= (const hzMapM<KEY,OBJ>&) ;
public:
hzMapM (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_numMmaps++ ;
}
hzMapM (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_numMmaps++ ;
}
hzMapM (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_numMmaps++ ;
}
hzMapM (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_numMmaps++ ;
}
~hzMapM (void) { _hzGlobal_Memstats.m_numMmaps-- ; }
// Init functions
void SetName (const hzString& name) { base.SetName(name) ; }
void SetLock (hzLockOpt eLock) { base.SetLock(eLock) ; }
void Clear (void) { base.Clear() ; }
// Insert and delete by key
hzEcode Insert (const KEY& key, const OBJ& obj)
{
_hzfunc("hzMapM::Insert") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ;
int32_t nSlot ;
pDN = base.InsertKeyM(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("hzMapM:Delete") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_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) ;
//pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ;
//pBuck->m_Keys[nSlot] = m_NullKey ;
//pBuck->m_Objs[nSlot] = m_NullObj ;
return E_OK ;
}
hzEcode Delete (uint32_t nPosn)
{
_hzfunc("hzMapM:Delete(Posn)") ;
_hz_map_bkt<KEY,OBJ>* pBuck ;
_hz_vn_Dat* pDN ;
int32_t nSlot ;
pDN = base._findDnodeByPos(nSlot, nPosn, HZ_ISAMSRCH_LO) ;
if (pDN)
return E_NOTFOUND ;
pBuck = (_hz_map_bkt<KEY,OBJ>*) pDN->m_pElements ;
pBuck->m_Keys[nSlot] = m_NullKey ;
pBuck->m_Objs[nSlot] = m_NullObj ;
return base.DeletePosn(nPosn) ;
}
// Locate keys or objects by position
OBJ& GetObj (uint32_t nIndex) const
{
_hzfunc("hzMapM: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("hzMapM: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("hzMapM: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("hzMapM: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] ;
}
// Iteration support functions
int32_t First (const KEY key) const
{
_hzfunc("hzMapM:First") ;
_hz_vn_Dat* pDN ;
uint32_t nPosn ;
int32_t nSlot ;
if ((pDN = base._findAllByKey(nSlot, nPosn, &key, HZ_ISAMSRCH_LO)))
{
return 0x7fffffff & nPosn ;
}
return -1 ;
}
int32_t Last (const KEY key) const
{
_hzfunc("hzMapM:Last") ;
_hz_vn_Dat* pDN ;
uint32_t nPosn ;
int32_t nSlot ;
if ((pDN = base._findAllByKey(nSlot, nPosn, &key, HZ_ISAMSRCH_HI)))
{
return 0x7fffffff & nPosn ;
}
return -1 ;
}
int32_t Target (const KEY key) const
{
_hzfunc("hzMapM:Target") ;
_hz_vn_Dat* pDN ;
uint32_t nPosn ;
int32_t nSlot ;
if ((pDN = 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) ; }
} ;
/*
** The hzSet template
*/
#endif // hzTmplMapM_h