/****************************************************************************** Header File: Utility Classes.CPP These classes are generally useful classes which can be used for a variety of purposes. I created this separate file for quicker reuse later, and also to avoid having to include some very specific header file just to get these general-purpose classes. Copyright (c) 1997 by Microsoft Corporation. All Rights Reserved. A Pretty Penny Enterprises Production Change History: 03-01-1997 Bob_Kjelgaard@Prodigy.Net Created it ******************************************************************************/ #include "StdAfx.H" #if defined(LONG_NAMES) #include "Utility Classes.H" #else #include "Utility.H" #endif /****************************************************************************** CMapWordToDWord class This class uses CMapWordToPtr to do its dirty work. When the need arises, I will make it serializable ******************************************************************************/ BOOL CMapWordToDWord::Lookup(WORD wKey, DWORD& dwItem) const { union { void* pv; DWORD dw; }; if (!CMapWordToPtr::Lookup(wKey, pv)) return FALSE; dwItem = dw; return TRUE; } /****************************************************************************** CMapWordToDWord::GetNextAssoc This is the map iteration method. We call the same method on the bas class, and update the DWORD parameter if the underlying method is successful. ******************************************************************************/ void CMapWordToDWord::GetNextAssoc(POSITION& pos, WORD& wKey, DWORD& dwItem) const { union { void* pv; DWORD dw; }; CMapWordToPtr::GetNextAssoc(pos, wKey, pv); dwItem = dw; } /****************************************************************************** CMapWordToDWord::Operator[] This implements an l-value only operator usable for adding new associations or updating existing ones. ******************************************************************************/ DWORD& CMapWordToDWord::operator[](WORD wKey) { return (DWORD&) CMapWordToPtr::operator[](wKey); } /****************************************************************************** CSafeObArray class implementation This provides a "Safe" CObArray class which can't leak! ******************************************************************************/ IMPLEMENT_SERIAL(CSafeObArray, CObject, 0); /****************************************************************************** CSafeObArray::~CSafeObArray The class destructor will delete the object foreach non-NULL pointer in the array. ******************************************************************************/ CSafeObArray::~CSafeObArray() { for (unsigned u = 0; u < GetSize(); u++) if (m_coa[u]) delete m_coa[u]; } /****************************************************************************** CSafeObArray::RemoveAll Almost the same as the destructor, isn't it? ******************************************************************************/ void CSafeObArray::RemoveAll() { for (unsigned u = 0; u < GetSize(); u++) if (m_coa[u]) delete m_coa[u]; m_coa.RemoveAll(); } /****************************************************************************** CSafeObArray::RemoveAt This removes one element from the array- after deleting it, of course. ******************************************************************************/ void CSafeObArray::RemoveAt(int i) { if (m_coa[i]) delete m_coa[i]; m_coa.RemoveAt(i); } /****************************************************************************** CSafeObArray::Copy Copy the contents of one array to another. ******************************************************************************/ void CSafeObArray::Copy(CSafeObArray& csoa) { m_coa.Copy(*(csoa.GetCOA())) ; } /****************************************************************************** CSafeObArray::Serialize I call the CObject serializer to maintain the proper typ einformation, then let the CObArray serialize itself. ******************************************************************************/ void CSafeObArray::Serialize(CArchive& car) { if (car.IsLoading()) RemoveAll(); CObject::Serialize(car); m_coa.Serialize(car); } /****************************************************************************** CSafeMapWordToOb implementation Making the workd safe for maps. ******************************************************************************/ IMPLEMENT_SERIAL(CSafeMapWordToOb, CObject, 0) /****************************************************************************** CSafeMapWordToOb::~CSafeMapWordToOb The class destructor must ensure the underlying objects are deleted. ******************************************************************************/ CSafeMapWordToOb::~CSafeMapWordToOb() { WORD wKey; CObject *pco; for (POSITION pos = m_cmw2o.GetStartPosition(); pos; ) { m_cmw2o.GetNextAssoc(pos, wKey, pco); if (pco) delete pco; } } /****************************************************************************** CSafeMapWordToOb::operator[] The problem here is that this is used only to put elements in the map- therefore, I intercept the call and delete any existing item. This could cause problems if the same pointer is re-inserted into the map, but for now, I'll take my chances. ******************************************************************************/ CObject*& CSafeMapWordToOb::operator[](WORD wKey) { CObject*& pco = m_cmw2o.operator[](wKey); if (pco) delete pco; return pco; } /****************************************************************************** CSafeMapWordToOb::RemoveKey Pretty Obvious- if there was an object there, remove it. ******************************************************************************/ BOOL CSafeMapWordToOb::RemoveKey(WORD wKey) { CObject *pco; if (!m_cmw2o.Lookup(wKey, pco)) return FALSE; if (pco) delete pco; return m_cmw2o.RemoveKey(wKey); } /****************************************************************************** CSafeMapWordToOb::RemoveAll Again, this is pretty obvious- destroy anything that lives! ******************************************************************************/ void CSafeMapWordToOb::RemoveAll() { WORD wKey; CObject *pco; for (POSITION pos = m_cmw2o.GetStartPosition(); pos; ) { GetNextAssoc(pos, wKey, pco); if (pco) delete pco; } m_cmw2o.RemoveAll(); } /****************************************************************************** CSafeMapWordToOb::Serialize First, I depopulate the map if it is being loaded. Then I call the CObject serializer to handle run-time typing checks, and then serialize the underlying map. ******************************************************************************/ void CSafeMapWordToOb::Serialize(CArchive& car) { if (car.IsLoading()) RemoveAll(); CObject::Serialize(car); m_cmw2o.Serialize(car); }