/***************************************************************************** * * (C) COPYRIGHT MICROSOFT CORPORATION, 2000 * * TITLE: cntutils.h * * VERSION: 1.0 * * AUTHOR: LazarI * * DATE: 23-Dec-2000 * * DESCRIPTION: Containers and algorithms utility templates * *****************************************************************************/ #ifndef _CNTUTILS_H #define _CNTUTILS_H // the generic smart pointers & handles #include "gensph.h" //////////////////////////////////////////////// // Algorithms // namespace Alg { /////////////////////////////////////////////////////////////// // CDefaultAdaptor - default adaptor class. // // T - type // K - key for sorting // template class CDefaultAdaptor { public: // assumes the key is the item itself static const K& Key(const T &i) { return (const K&)i; } // assumes K has less operator defined static int Compare(const K &k1, const K &k2) { return (k2 < k1) - (k1 < k2); } // assumes assignment operator defined static T& Assign(T &i1, const T &i2) { return (i1 = i2); } }; ////////////////////////////////////////////////////////// // _LowerBound - lowerbound search alg. // assumes the array is sorted. // // returns the position where this key (item) should be inserted. // all the items before that position will be less or equal to the input key // // T - type // K - key for sorting // A - adaptor // template int _LowerBound(const K &k, const T *base, int lo, int hi) { while( lo <= hi ) { if( lo == hi ) { // boundary case if( A::Compare(k, A::Key(base[lo])) >= 0 ) { // k >= lo lo++; } break; } else { // divide & conquer int mid = (lo+hi)/2; if( A::Compare(k, A::Key(base[mid])) < 0 ) { // k < mid hi = mid; } else { // k >= mid lo = mid+1; } } } return lo; } /////////////////////////////////////////////////////////////// // CSearchAlgorithms - search alg. // // T - type // K - key for sorting // A - adaptor // // default template arguments are allowed only on classes template > class CSearchAlgorithms { public: // lower bound static int LowerBound(const K &k, const T *base, int count) { return _LowerBound(k, base, 0, count-1); } // binary search static bool Find(const K &k, const T *base, int count, int *pi) { int iPos = _LowerBound(k, base, 0, count-1)-1; bool bFound = (0 <= iPos && iPos < count && 0 == A::Compare(k, A::Key(base[iPos]))); if( bFound && pi ) *pi = iPos; return bFound; }; }; } // namespace Alg //////////////////////////////////////////////// // // class CSimpleArray // // a simple array implementation based on // shell DSA_* stuff (not MT safe) // // turn off debugging new for a while #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) #undef new #endif template class CSimpleArray { // in-place construct/destruct wrapper class CWrapper { public: // proper copy semantics CWrapper() { } CWrapper(const T &t): m_t(t) { } T& operator = (const T &t) { m_t = t; return t; } // placed new & delete void *operator new(size_t, CWrapper *p) { ASSERT(p); return p; } void operator delete(void *p) { } T m_t; }; public: enum { DEFAULT_GROW = 32 }; typedef int (*PFN_COMPARE)(const T &i1, const T &i2); CSimpleArray(int iGrow = DEFAULT_GROW) { Create(iGrow); } ~CSimpleArray() { Destroy(); } HRESULT Create(int iGrow = DEFAULT_GROW) { m_shDSA = DSA_Create(sizeof(CWrapper), iGrow); return m_shDSA ? S_OK : E_OUTOFMEMORY; } HRESULT Destroy() { if( m_shDSA ) { DeleteAll(); m_shDSA = NULL; } return S_OK; } // the array interface int Count() const { ASSERT(m_shDSA); return _DSA_GetItemCount(m_shDSA); } const T& operator [] (int i) const { return _GetWrapperAt(i)->m_t; } T& operator [] (int i) { return _GetWrapperAt(i)->m_t; } // returns true if created/initialized operator bool () const { return m_shDSA; } // returns -1 if failed to grow - i.e. out of memory int Append(const T &item) { ASSERT(m_shDSA); int i = DSA_InsertItem(m_shDSA, DA_LAST, (void *)_GetZeroMemWrapper()); // allocate if( -1 != i ) { new (_GetWrapperAt(i)) CWrapper(item); // construct } return i; } // returns -1 if failed to grow - i.e. out of memory int Insert(int i, const T &item) { ASSERT(m_shDSA && 0 <= i && i <= _DSA_GetItemCount(m_shDSA)); i = DSA_InsertItem(m_shDSA, i, (void *)_GetZeroMemWrapper()); // allocate if( -1 != i ) { new (_GetWrapperAt(i)) CWrapper(item); // construct } return i; } BOOL Delete(int i) { ASSERT(m_shDSA && 0 <= i && i < _DSA_GetItemCount(m_shDSA)); delete _GetWrapperAt(i); // destruct return DSA_DeleteItem(m_shDSA, i); // free } void DeleteAll() { ASSERT(m_shDSA); // destruct all if( Count() ) { int i, iCount = Count(); CWrapper *p = _GetWrapperAt(0); for( i=0; i(buffer); } CWrapper* _GetWrapperAt(int i) const { ASSERT(m_shDSA && 0 <= i && i < _DSA_GetItemCount(m_shDSA)); return reinterpret_cast(DSA_GetItemPtr(m_shDSA, i)); } int _DSA_GetItemCount(HDSA hdsa) const { // DSA_GetItemCount is a macro, which is casting to int* (somewhat illegal), // so we need to do a static cast here, so our casting operator gets invoked return DSA_GetItemCount(static_cast(m_shDSA)); } CAutoHandleHDSA m_shDSA; // shell dynamic structure array }; // turn back on debugging new #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif //////////////////////////////////////////////// // // class CSortedArray // // a sorted array implementation based on DSA_* // (not MT safe) // // T - type // K - key for sorting // A - adaptor // template > class CSortedArray: public CSimpleArray { public: CSortedArray() { } CSortedArray(int iGrow): CSimpleArray(iGrow) { } ~CSortedArray() { } // returns -1 if failed to grow - i.e. out of memory int SortedInsert(const T &item) { return CSimpleArray::Insert( Count() ? Alg::CSearchAlgorithms::LowerBound(A::Key(item), &operator[](0), Count()) : 0, item); } // true if found and false otherwise bool FindItem(const K &k, int *pi) const { return Count() ? Alg::CSearchAlgorithms::Find(k, &operator[](0), Count(), pi) : false; } private: // those APIs shouldn't be visible, so make them private. int Append(const T &item) { CSimpleArray::Append(item); } int Insert(int i, const T &item) { CSimpleArray::Insert(i, item); } HRESULT Sort(PFN_COMPARE pfnCompare) { CSimpleArray::Sort(pfnCompare); } }; //////////////////////////////////////////////// // // class CFastHeap // // fast cached heap for fixed chunks // of memory (MT safe) // template class CFastHeap { public: enum { DEFAULT_CACHE_SIZE = 32 }; // construction/destruction CFastHeap(int iCacheSize = DEFAULT_CACHE_SIZE); ~CFastHeap(); // the fast heap interface HRESULT Alloc(const T &data, HANDLE *ph); HRESULT Free(HANDLE h); HRESULT GetItem(HANDLE h, T **ppData); #if DBG int m_iPhysicalAllocs; int m_iLogicalAllocs; #else private: #endif // private stuff/impl. struct HeapItem { HeapItem *pNext; T data; }; CCSLock m_csLock; HeapItem *m_pFreeList; int m_iCacheSize; int m_iCached; }; // include the implementation of the template classes here #include "cntutils.inl" #endif // endif _CNTUTILS_H