?? afxtempl.h
字號:
m_nCount++;
ASSERT(m_nCount > 0); // make sure we don't overflow
ConstructElements<KEY>(&pAssoc->key, 1);
ConstructElements<VALUE>(&pAssoc->value, 1); // special construct values
return pAssoc;
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::FreeAssoc(CMap::CAssoc* pAssoc)
{
DestructElements<VALUE>(&pAssoc->value, 1);
DestructElements<KEY>(&pAssoc->key, 1);
pAssoc->pNext = m_pFreeList;
m_pFreeList = pAssoc;
m_nCount--;
ASSERT(m_nCount >= 0); // make sure we don't underflow
// if no more elements, cleanup completely
if (m_nCount == 0)
RemoveAll();
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAssocAt(ARG_KEY key, UINT& nHash) const
// find association (or return NULL)
{
nHash = HashKey<ARG_KEY>(key) % m_nHashTableSize;
if (m_pHashTable == NULL)
return NULL;
// see if it exists
CAssoc* pAssoc;
for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
{
if (CompareElements(&pAssoc->key, &key))
return pAssoc;
}
return NULL;
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key, VALUE& rValue) const
{
ASSERT_VALID(this);
UINT nHash;
CAssoc* pAssoc = GetAssocAt(key, nHash);
if (pAssoc == NULL)
return FALSE; // not in map
rValue = pAssoc->value;
return TRUE;
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
VALUE& CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator[](ARG_KEY key)
{
ASSERT_VALID(this);
UINT nHash;
CAssoc* pAssoc;
if ((pAssoc = GetAssocAt(key, nHash)) == NULL)
{
if (m_pHashTable == NULL)
InitHashTable(m_nHashTableSize);
// it doesn't exist, add a new Association
pAssoc = NewAssoc();
pAssoc->nHashValue = nHash;
pAssoc->key = key;
// 'pAssoc->value' is a constructed object, nothing more
// put into hash table
pAssoc->pNext = m_pHashTable[nHash];
m_pHashTable[nHash] = pAssoc;
}
return pAssoc->value; // return new reference
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveKey(ARG_KEY key)
// remove key - return TRUE if removed
{
ASSERT_VALID(this);
if (m_pHashTable == NULL)
return FALSE; // nothing in the table
CAssoc** ppAssocPrev;
ppAssocPrev = &m_pHashTable[HashKey<ARG_KEY>(key) % m_nHashTableSize];
CAssoc* pAssoc;
for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
{
if (CompareElements(&pAssoc->key, &key))
{
// remove it
*ppAssocPrev = pAssoc->pNext; // remove from list
FreeAssoc(pAssoc);
return TRUE;
}
ppAssocPrev = &pAssoc->pNext;
}
return FALSE; // not found
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetNextAssoc(POSITION& rNextPosition,
KEY& rKey, VALUE& rValue) const
{
ASSERT_VALID(this);
ASSERT(m_pHashTable != NULL); // never call on empty map
CAssoc* pAssocRet = (CAssoc*)rNextPosition;
ASSERT(pAssocRet != NULL);
if (pAssocRet == (CAssoc*) BEFORE_START_POSITION)
{
// find the first association
for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
break;
ASSERT(pAssocRet != NULL); // must find something
}
// find next association
ASSERT(AfxIsValidAddress(pAssocRet, sizeof(CAssoc)));
CAssoc* pAssocNext;
if ((pAssocNext = pAssocRet->pNext) == NULL)
{
// go to next bucket
for (UINT nBucket = pAssocRet->nHashValue + 1;
nBucket < m_nHashTableSize; nBucket++)
if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
break;
}
rNextPosition = (POSITION) pAssocNext;
// fill in return data
rKey = pAssocRet->key;
rValue = pAssocRet->value;
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar.IsStoring())
{
ar.WriteCount(m_nCount);
if (m_nCount == 0)
return; // nothing more to do
ASSERT(m_pHashTable != NULL);
for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
{
CAssoc* pAssoc;
for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
pAssoc = pAssoc->pNext)
{
SerializeElements<KEY>(ar, &pAssoc->key, 1);
SerializeElements<VALUE>(ar, &pAssoc->value, 1);
}
}
}
else
{
DWORD nNewCount = ar.ReadCount();
while (nNewCount--)
{
KEY newKey;
VALUE newValue;
SerializeElements<KEY>(ar, &newKey, 1);
SerializeElements<VALUE>(ar, &newValue, 1);
SetAt(newKey, newValue);
}
}
}
#ifdef _DEBUG
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "with " << m_nCount << " elements";
if (dc.GetDepth() > 0)
{
// Dump in format "[key] -> value"
KEY key;
VALUE val;
POSITION pos = GetStartPosition();
while (pos != NULL)
{
GetNextAssoc(pos, key, val);
dc << "\n\t[";
DumpElements<KEY>(dc, &key, 1);
dc << "] = ";
DumpElements<VALUE>(dc, &val, 1);
}
}
dc << "\n";
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_nHashTableSize > 0);
ASSERT(m_nCount == 0 || m_pHashTable != NULL);
// non-empty map should have hash table
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTypedPtrArray<BASE_CLASS, TYPE>
template<class BASE_CLASS, class TYPE>
class CTypedPtrArray : public BASE_CLASS
{
public:
// Accessing elements
TYPE GetAt(int nIndex) const
{ return (TYPE)BASE_CLASS::GetAt(nIndex); }
TYPE& ElementAt(int nIndex)
{ return (TYPE&)BASE_CLASS::ElementAt(nIndex); }
void SetAt(int nIndex, TYPE ptr)
{ BASE_CLASS::SetAt(nIndex, ptr); }
// Potentially growing the array
void SetAtGrow(int nIndex, TYPE newElement)
{ BASE_CLASS::SetAtGrow(nIndex, newElement); }
int Add(TYPE newElement)
{ return BASE_CLASS::Add(newElement); }
int Append(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
{ return BASE_CLASS::Append(src); }
void Copy(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
{ BASE_CLASS::Copy(src); }
// Operations that move elements around
void InsertAt(int nIndex, TYPE newElement, int nCount = 1)
{ BASE_CLASS::InsertAt(nIndex, newElement, nCount); }
void InsertAt(int nStartIndex, CTypedPtrArray<BASE_CLASS, TYPE>* pNewArray)
{ BASE_CLASS::InsertAt(nStartIndex, pNewArray); }
// overloaded operator helpers
TYPE operator[](int nIndex) const
{ return (TYPE)BASE_CLASS::operator[](nIndex); }
TYPE& operator[](int nIndex)
{ return (TYPE&)BASE_CLASS::operator[](nIndex); }
};
/////////////////////////////////////////////////////////////////////////////
// CTypedPtrList<BASE_CLASS, TYPE>
template<class BASE_CLASS, class TYPE>
class _CTypedPtrList : public BASE_CLASS
{
public:
// Construction
_CTypedPtrList(int nBlockSize = 10)
: BASE_CLASS(nBlockSize) { }
// peek at head or tail
TYPE& GetHead()
{ return (TYPE&)BASE_CLASS::GetHead(); }
TYPE GetHead() const
{ return (TYPE)BASE_CLASS::GetHead(); }
TYPE& GetTail()
{ return (TYPE&)BASE_CLASS::GetTail(); }
TYPE GetTail() const
{ return (TYPE)BASE_CLASS::GetTail(); }
// get head or tail (and remove it) - don't call on empty list!
TYPE RemoveHead()
{ return (TYPE)BASE_CLASS::RemoveHead(); }
TYPE RemoveTail()
{ return (TYPE)BASE_CLASS::RemoveTail(); }
// iteration
TYPE& GetNext(POSITION& rPosition)
{ return (TYPE&)BASE_CLASS::GetNext(rPosition); }
TYPE GetNext(POSITION& rPosition) const
{ return (TYPE)BASE_CLASS::GetNext(rPosition); }
TYPE& GetPrev(POSITION& rPosition)
{ return (TYPE&)BASE_CLASS::GetPrev(rPosition); }
TYPE GetPrev(POSITION& rPosition) const
{ return (TYPE)BASE_CLASS::GetPrev(rPosition); }
// getting/modifying an element at a given position
TYPE& GetAt(POSITION position)
{ return (TYPE&)BASE_CLASS::GetAt(position); }
TYPE GetAt(POSITION position) const
{ return (TYPE)BASE_CLASS::GetAt(position); }
void SetAt(POSITION pos, TYPE newElement)
{ BASE_CLASS::SetAt(pos, newElement); }
};
template<class BASE_CLASS, class TYPE>
class CTypedPtrList : public _CTypedPtrList<BASE_CLASS, TYPE>
{
public:
// Construction
CTypedPtrList(int nBlockSize = 10)
: _CTypedPtrList<BASE_CLASS, TYPE>(nBlockSize) { }
// add before head or after tail
POSITION AddHead(TYPE newElement)
{ return BASE_CLASS::AddHead(newElement); }
POSITION AddTail(TYPE newElement)
{ return BASE_CLASS::AddTail(newElement); }
// add another list of elements before head or after tail
void AddHead(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ BASE_CLASS::AddHead(pNewList); }
void AddTail(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ BASE_CLASS::AddTail(pNewList); }
};
// need specialized version for CObList because of AddHead/Tail ambiguity
template<> class CTypedPtrList<CObList, CObList*>
: public _CTypedPtrList<CObList, CObList*>
{
public:
// Construction
CTypedPtrList(int nBlockSize = 10)
: _CTypedPtrList<CObList, CObList*>(nBlockSize) { }
// add before head or after tail
POSITION AddHead(TYPE newElement)
{ return _CTypedPtrList<CObList, CObList*>::AddHead((CObject*)newElement); }
POSITION AddTail(TYPE newElement)
{ return _CTypedPtrList<CObList, CObList*>::AddTail((CObject*)newElement); }
// add another list of elements before head or after tail
void AddHead(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ _CTypedPtrList<CObList, CObList*>::AddHead(pNewList); }
void AddTail(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ _CTypedPtrList<CObList, CObList*>::AddTail(pNewList); }
};
// need specialized version for CPtrList because of AddHead/Tail ambiguity
template<> class CTypedPtrList<CPtrList, CPtrList*>
: public _CTypedPtrList<CPtrList, CPtrList*>
{
public:
// Construction
CTypedPtrList(int nBlockSize = 10)
: _CTypedPtrList<CPtrList, CPtrList*>(nBlockSize) { }
// add before head or after tail
POSITION AddHead(TYPE newElement)
{ return _CTypedPtrList<CPtrList, CPtrList*>::AddHead((void*)newElement); }
POSITION AddTail(TYPE newElement)
{ return _CTypedPtrList<CPtrList, CPtrList*>::AddTail((void*)newElement); }
// add another list of elements before head or after tail
void AddHead(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ _CTypedPtrList<CPtrList, CPtrList*>::AddHead(pNewList); }
void AddTail(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
{ _CTypedPtrList<CPtrList, CPtrList*>::AddTail(pNewList); }
};
/////////////////////////////////////////////////////////////////////////////
// CTypedPtrMap<BASE_CLASS, KEY, VALUE>
template<class BASE_CLASS, class KEY, class VALUE>
class CTypedPtrMap : public BASE_CLASS
{
public:
// Construction
CTypedPtrMap(int nBlockSize = 10)
: BASE_CLASS(nBlockSize) { }
// Lookup
BOOL Lookup(BASE_CLASS::BASE_ARG_KEY key, VALUE& rValue) const
{ return BASE_CLASS::Lookup(key, (BASE_CLASS::BASE_VALUE&)rValue); }
// Lookup and add if not there
VALUE& operator[](BASE_CLASS::BASE_ARG_KEY key)
{ return (VALUE&)BASE_CLASS::operator[](key); }
// add a new key (key, value) pair
void SetAt(KEY key, VALUE newValue)
{ BASE_CLASS::SetAt(key, newValue); }
// removing existing (key, ?) pair
BOOL RemoveKey(KEY key)
{ return BASE_CLASS::RemoveKey(key); }
// iteration
void GetNextAssoc(POSITION& rPosition, KEY& rKey, VALUE& rValue) const
{ BASE_CLASS::GetNextAssoc(rPosition, (BASE_CLASS::BASE_KEY&)rKey,
(BASE_CLASS::BASE_VALUE&)rValue); }
};
/////////////////////////////////////////////////////////////////////////////
#undef THIS_FILE
#define THIS_FILE __FILE__
#undef new
#ifdef _REDEF_NEW
#define new DEBUG_NEW
#undef _REDEF_NEW
#endif
#ifdef _AFX_PACKING
#pragma pack(pop)
#endif
#ifdef _AFX_MINREBUILD
#pragma component(minrebuild, on)
#endif
#ifndef _AFX_FULLTYPEINFO
#pragma component(mintypeinfo, off)
#endif
#endif //__AFXTEMPL_H__
/////////////////////////////////////////////////////////////////////////////
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -