From 4ae1a330bdbb4ea1f34dd528d8743883b7bff244 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 23 Oct 1998 00:20:41 +0000 Subject: [PATCH] attempted to clean up HP-UX warnings --- src/cxxTemplates/resourceLib.h | 281 ++++++----- src/cxxTemplates/tsDLList.h | 639 ++++++++++++++++---------- src/cxxTemplates/tsSLList.h | 157 ++++--- src/libCom/cxxTemplates/resourceLib.h | 281 ++++++----- src/libCom/cxxTemplates/tsDLList.h | 639 ++++++++++++++++---------- src/libCom/cxxTemplates/tsSLList.h | 157 ++++--- 6 files changed, 1310 insertions(+), 844 deletions(-) diff --git a/src/cxxTemplates/resourceLib.h b/src/cxxTemplates/resourceLib.h index 66a3e8c43..ffe6c8c89 100644 --- a/src/cxxTemplates/resourceLib.h +++ b/src/cxxTemplates/resourceLib.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.17 1998/06/16 03:00:19 jhill + * cleaned up fast string hash table + * * Revision 1.16 1998/04/10 23:07:33 jhill * fixed solaris architecture specific problem where xxx>>32 was ignored * @@ -129,14 +132,7 @@ public: int init(unsigned nHashTableEntries); - ~resTable() - { - if (this->pTable) { - this->destroyAllEntries(); - assert (this->nInUse == 0u); - delete [] this->pTable; - } - } + virtual ~resTable(); // // destroy all res in the table @@ -240,6 +236,7 @@ private: class epicsShareClass uintId { public: uintId (unsigned idIn=UINT_MAX) : id(idIn) {} + virtual ~uintId(); int operator == (const uintId &idIn) { @@ -259,38 +256,6 @@ protected: unsigned id; }; -// -// this needs to be instanciated only once (normally in libCom) -// -#ifdef instantiateRecourceLib -// -// uintId::resourceHash() -// -resTableIndex uintId::resourceHash(unsigned /* nBitsId */) const -{ - resTableIndex hashid = this->id; - - // - // This assumes worst case hash table index width of 1 bit. - // We will iterate this loop 5 times on a 32 bit architecture. - // - // A good optimizer will unroll this loop? - // Experiments using the microsoft compiler show that this isnt - // slower than switching on the architecture size and urolling the - // loop explicitly (that solution has resulted in portability - // problems in the past). - // - for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) { - hashid ^= (hashid>>i); - } - - // - // the result here is always masked to the - // proper size after it is returned to the resource class - // - return hashid; -} -#endif // instantiateRecourceLib // // special resource table which uses @@ -302,6 +267,7 @@ template class uintResTable : public resTable { public: uintResTable() : allocId(1u) {} // hashing is faster close to zero + virtual ~uintResTable(); inline void installItem(ITEM &item); private: @@ -316,6 +282,7 @@ class uintRes : public uintId, public tsSLNode { friend class uintResTable; public: uintRes(unsigned idIn=UINT_MAX) : uintId(idIn) {} + virtual ~uintRes(); private: // // workaround for bug in DEC compiler @@ -323,23 +290,6 @@ private: void setId(unsigned newId) {this->id = newId;} }; -// -// uintRes::installItem() -// -// NOTE: This detects (and avoids) the case where -// the PV id wraps around and we attempt to have two -// resources with the same id. -// -template -inline void uintResTable::installItem(ITEM &item) -{ - int resTblStatus; - do { - item.uintRes::setId(allocId++); - resTblStatus = this->add(item); - } - while (resTblStatus); -} // // character string identifier @@ -379,14 +329,7 @@ public: pStr(typeIn==copyString?allocCopyString(idIn):idIn), allocType(typeIn) {} - ~ stringId() - { - if (this->allocType==copyString) { - if (this->pStr!=NULL) { - delete [] (char *) this->pStr; - } - } - } + virtual ~ stringId(); // // The hash algorithm is a modification of the algorithm described in @@ -428,54 +371,6 @@ private: static const unsigned char stringIdFastHash[256]; }; -// -// this needs to be instanciated only once (normally in libCom) -// -#ifdef instantiateRecourceLib -// -// stringId::resourceHash() -// -// The hash algorithm is a modification of the algorithm described in -// Fast Hashing of Variable Length Text Strings, Peter K. Pearson, -// Communications of the ACM, June 1990 -// The modifications were designed by Marty Kraimer -// -resTableIndex stringId::resourceHash(unsigned nBitsId) const -{ - if (this->pStr==NULL) { - return 0u; - } - - unsigned h0 = 0u; - unsigned h1 = 0u; - unsigned c; - unsigned i; - for (i=0u; (c = this->pStr[i]); i++) { - // - // odd - // - if (i&1u) { - h1 = stringIdFastHash[h1 ^ c]; - } - // - // even - // - else { - h0 = stringIdFastHash[h0 ^ c]; - } - } - - // - // does not work well for more than 65k entries ? - // (because some indexes in the table will not be produced) - // - if (nBitsId>=8u) { - h1 = h1 << (nBitsId-8u); - } - return h1 ^ h0; -} -#endif // instantiateRecourceLib - // // resTable::init() // @@ -691,6 +586,165 @@ T *resTable::findDelete (tsSLList &list, const ID &idIn) return pItem; } +// +// ~resTable::resTable() +// +template +resTable::~resTable() +{ + if (this->pTable) { + this->destroyAllEntries(); + assert (this->nInUse == 0u); + delete [] this->pTable; + } +} + +// +// uintResTable::~uintResTable() +// (not inline because it is virtual) +// +template +uintResTable::~uintResTable() {} + +// +// uintRes::~uintRes() +// (not inline because it is virtual) +// +template +uintRes::~uintRes() {} + +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +// +// uintId::resourceHash() +// +resTableIndex uintId::resourceHash(unsigned /* nBitsId */) const +{ + resTableIndex hashid = this->id; + + // + // This assumes worst case hash table index width of 1 bit. + // We will iterate this loop 5 times on a 32 bit architecture. + // + // A good optimizer will unroll this loop? + // Experiments using the microsoft compiler show that this isnt + // slower than switching on the architecture size and urolling the + // loop explicitly (that solution has resulted in portability + // problems in the past). + // + for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) { + hashid ^= (hashid>>i); + } + + // + // the result here is always masked to the + // proper size after it is returned to the resource class + // + return hashid; +} + +// +// uintResTable::~uintResTable() +// (not inline because it is virtual) +// +uintId::~uintId() {} + +#endif // instantiateRecourceLib + +// +// uintRes::installItem() +// +// NOTE: This detects (and avoids) the case where +// the PV id wraps around and we attempt to have two +// resources with the same id. +// +template +inline void uintResTable::installItem(ITEM &item) +{ + int resTblStatus; + do { + item.uintRes::setId(allocId++); + resTblStatus = this->add(item); + } + while (resTblStatus); +} + +// +// stringId::~stringId() +// +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +stringId::~stringId() +{ + if (this->allocType==copyString) { + if (this->pStr!=NULL) { +#ifdef _MSC_VER + // + // bugs in microsloth visual C++ appear to require + // a const cast away here + // + delete [] (char * const) this->pStr; +#else + delete [] this->pStr; +#endif + + } + } +} +#endif // instantiateRecourceLib + +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +// +// stringId::resourceHash() +// +// The hash algorithm is a modification of the algorithm described in +// Fast Hashing of Variable Length Text Strings, Peter K. Pearson, +// Communications of the ACM, June 1990 +// The modifications were designed by Marty Kraimer +// +resTableIndex stringId::resourceHash(unsigned nBitsId) const +{ + if (this->pStr==NULL) { + return 0u; + } + + unsigned h0 = 0u; + unsigned h1 = 0u; + unsigned c; + unsigned i; + for (i=0u; (c = this->pStr[i]); i++) { + // + // odd + // + if (i&1u) { + h1 = stringIdFastHash[h1 ^ c]; + } + // + // even + // + else { + h0 = stringIdFastHash[h0 ^ c]; + } + } + + // + // does not work well for more than 65k entries ? + // (because some indexes in the table will not be produced) + // + if (nBitsId>=8u) { + h1 = h1 << (nBitsId-8u); + } + return h1 ^ h0; +} +#endif // instantiateRecourceLib + // // this needs to be instanciated only once (normally in libCom) // @@ -719,6 +773,7 @@ const unsigned char stringId::stringIdFastHash[256] = { 111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238, 134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47 }; + #endif // instantiateRecourceLib #endif // INCresourceLibh diff --git a/src/cxxTemplates/tsDLList.h b/src/cxxTemplates/tsDLList.h index 62fa7032b..1495b6c9b 100644 --- a/src/cxxTemplates/tsDLList.h +++ b/src/cxxTemplates/tsDLList.h @@ -31,6 +31,9 @@ * * History * $Log$ + * Revision 1.13 1998/06/16 03:01:44 jhill + * cosmetic + * * Revision 1.12 1998/05/29 17:25:47 jhill * allow use of epicsAssert.h * @@ -151,183 +154,46 @@ public: // adds addList to the end of the list // (and removes all items from addList) // - void add (tsDLList &addList) - { - // - // NOOP if addList is empty - // - if (addList.itemCount==0u) { - return; - } - - if (this->itemCount==0u) { - // - // this is empty so just init from - // addList - // - *this = addList; - } - else { - tsDLNode *pLastNode = this->pLast; - tsDLNode *pAddListFirstNode = addList.pFirst; - - // - // add addList to the end of this - // - pLastNode->pNext = addList.pFirst; - pAddListFirstNode->pPrev = addList.pLast; - this->pLast = addList.pLast; - this->itemCount += addList.itemCount; - } - - // - // leave addList empty - // - addList.clear(); - } + void add (tsDLList &addList); // // add() // (add an item to the end of the list) // - void add (T &item) - { - tsDLNode &node = item; - - node.pNext = 0; - node.pPrev = this->pLast; - - if (this->itemCount) { - tsDLNode *pLastNode = this->pLast; - pLastNode->pNext = &item; - } - else { - this->pFirst = &item; - } - - this->pLast = &item; - - this->itemCount++; - } + void add (T &item); // // get () // - T * get() - { - T *pItem = this->pFirst; - - if (pItem) { - this->remove (*pItem); - } - - return pItem; - } + T * get(); // // insertAfter() // (place item in the list immediately after itemBefore) // - void insertAfter (T &item, T &itemBefore) - { - tsDLNode &node = item; - tsDLNode &nodeBefore = itemBefore; - - node.pPrev = &itemBefore; - node.pNext = nodeBefore.pNext; - nodeBefore.pNext = &item; - - if (node.pNext) { - tsDLNode *pNextNode = node.pNext; - pNextNode->pPrev = &item; - } - else { - this->pLast = &item; - } - - this->itemCount++; - } + void insertAfter (T &item, T &itemBefore); // // insertBefore () // (place item in the list immediately before itemAfter) // - void insertBefore (T &item, T &itemAfter) - { - tsDLNode &node = item; - tsDLNode &nodeAfter = itemAfter; - - node.pNext = &itemAfter; - node.pPrev = nodeAfter.pPrev; - nodeAfter.pPrev = &item; - - if (node.pPrev) { - tsDLNode *pPrevNode = node.pPrev; - pPrevNode->pNext = &item; - } - else { - this->pFirst = &item; - } - - this->itemCount++; - } + void insertBefore (T &item, T &itemAfter); // // remove () // - void remove (T &item) - { - tsDLNode &node = item; - - if (this->pLast == &item) { - this->pLast = node.pPrev; - } - else { - tsDLNode *pNextNode = node.pNext; - pNextNode->pPrev = node.pPrev; - } - - if (this->pFirst == &item) { - this->pFirst = node.pNext; - } - else { - tsDLNode *pPrevNode = node.pPrev; - pPrevNode->pNext = node.pNext; - } - - this->itemCount--; - } + void remove (T &item); // // pop () // (returns the first item on the list) - T * pop() - { - return this->get(); - } + T * pop(); // // push () // (add an item at the beginning of the list) // - void push (T &item) - { - tsDLNode &node = item; - node.pPrev = 0; - node.pNext = this->pFirst; - - if (this->itemCount) { - tsDLNode *pFirstNode = this->pFirst; - pFirstNode->pPrev = &item; - } - else { - this->pLast = &item; - } - - this->pFirst = &item; - - this->itemCount++; - } + void push (T &item); // // find @@ -364,6 +230,7 @@ private: tsDLList (const tsDLList &); }; + // // tsDLIterBD // (a bi-directional iterator in the style of the STL) @@ -377,8 +244,7 @@ public: tsDLIterBD (T *pInitialEntry) : pEntry(pInitialEntry) {} - tsDLIterBD (class tsDLIterBD ©In) : - pEntry(copyIn.pEntry) {} + tsDLIterBD (const class tsDLIterBD ©In); tsDLIterBD & operator = (T *pNewEntry) { @@ -459,7 +325,7 @@ public: private: T *pEntry; }; - + // // tsDLIter // @@ -474,7 +340,7 @@ private: template class tsDLIter { public: - tsDLIter (const tsDLList & listIn) : + tsDLIter (tsDLList & listIn) : pCurrent(0), pList(&listIn) {} void reset () @@ -493,33 +359,9 @@ public: this->reset(listIn); } - T * next () - { - T *pCur = this->pCurrent; - if (pCur==0) { - pCur = this->pList->pFirst; - } - else { - tsDLNode *pCurNode = pCur; - pCur = pCurNode->pNext; - } - this->pCurrent = pCur; - return pCur; - } + T * next (); - T * prev () - { - T *pCur = this->pCurrent; - if (pCur==0) { - pCur = this->pList->pLast; - } - else { - tsDLNode *pCurNode = pCur; - pCur = pCurNode->pPrev; - } - this->pCurrent = pCur; - return pCur; - } + T * prev (); T * first() { @@ -533,14 +375,11 @@ public: return this->pCurrent; } - T * operator () () - { - return this->next(); - } + T * operator () (); protected: T *pCurrent; - const tsDLList *pList; + tsDLList *pList; }; // @@ -561,30 +400,28 @@ protected: template class tsDLFwdIter: private tsDLIter { public: - tsDLFwdIter (const tsDLList &listIn) : + tsDLFwdIter (tsDLList &listIn) : tsDLIter(listIn) {} void reset () { this->tsDLIter::reset(); } + void reset (tsDLList &listIn) { this->tsDLIter::reset(listIn); } + void operator = (tsDLList &listIn) { this->tsDLIter::reset(listIn); } - T * operator () () - { - return this->tsDLIter::next(); - } - T * next () - { - tsDLIter &iterBase = *this; - return iterBase.next(); - } + + T * operator () (); + + T * next (); + T * first() { tsDLIter &iterBase = *this; @@ -600,31 +437,7 @@ public: // accessed sequentially even if an item // is removed) // - void remove () - { - T *pCur = this->pCurrent; - - if (pCur) { - tsDLNode *pCurNode = pCur; - - // - // strip const (we didnt declare the - // list const in the constructor) - // - tsDLList * pMutableList = - (tsDLList *) this->pList; - - // - // Move this->pCurrent to the previous item - // - this->pCurrent = pCurNode->pPrev; - - // - // delete current item - // - pMutableList->remove(*pCur); - } - } + void remove (); }; // @@ -645,29 +458,28 @@ public: template class tsDLBwdIter : private tsDLIter { public: - tsDLBwdIter(const tsDLList &listIn) : + tsDLBwdIter(tsDLList &listIn) : tsDLIter(listIn) {} void reset () { this->tsDLIter::reset(); } + void reset (tsDLList &listIn) { this->tsDLIter::reset(listIn); } + void operator = (tsDLList &listIn) { this->tsDLIter::reset(listIn); } - T * operator () () - { - return this->tsDLIter::prev(); - } - T * prev () - { - return this->tsDLIter::prev(); - } + + T * operator () (); + + T * prev (); + T * last() { return this->tsDLIter::last(); @@ -683,43 +495,366 @@ public: // accessed sequentially even if an item // is removed) // - void remove () - { - T *pCur = this->pCurrent; - - if (pCur) { - tsDLNode *pCurNode = pCur; - - // - // strip const (we didnt declare the - // list const in the constructor) - // - tsDLList * pMutableList = - (tsDLList *) this->pList; - - // - // Move this->pCurrent to the item after the - // item being deleted - // - this->pCurrent = pCurNode->pNext; - - // - // delete current item - // - pMutableList->remove(*pCur); - } - } + void remove (); }; +// +// MS Visual C 6.0 requires that this code is not provided in +// the class definition because the class isnt fully defined yet +// +template +inline tsDLIterBD::tsDLIterBD(const class tsDLIterBD ©In) : + pEntry(copyIn.pEntry) {} + // -// find +// tsDLList::remove () +// +template +void tsDLList::remove (T &item) +{ + tsDLNode &node = item; + + if (this->pLast == &item) { + this->pLast = node.pPrev; + } + else { + tsDLNode *pNextNode = node.pNext; + pNextNode->pPrev = node.pPrev; + } + + if (this->pFirst == &item) { + this->pFirst = node.pNext; + } + else { + tsDLNode *pPrevNode = node.pPrev; + pPrevNode->pNext = node.pNext; + } + + this->itemCount--; +} + +// +// tsDLList::get () +// +template +inline T * tsDLList::get() +{ + T *pItem = this->pFirst; + + if (pItem) { + this->remove (*pItem); + } + + return pItem; +} + +// +// tsDLList::pop () +// (returns the first item on the list) +template +inline T * tsDLList::pop() +{ + return this->get(); +} + +// +// add() - +// adds addList to the end of the list +// (and removes all items from addList) +// +template +void tsDLList::add (tsDLList &addList) +{ + // + // NOOP if addList is empty + // + if (addList.itemCount==0u) { + return; + } + + if (this->itemCount==0u) { + // + // this is empty so just init from + // addList + // + *this = addList; + } + else { + tsDLNode *pLastNode = this->pLast; + tsDLNode *pAddListFirstNode = addList.pFirst; + + // + // add addList to the end of this + // + pLastNode->pNext = addList.pFirst; + pAddListFirstNode->pPrev = addList.pLast; + this->pLast = addList.pLast; + this->itemCount += addList.itemCount; + } + + // + // leave addList empty + // + addList.clear(); +} + +// +// add() +// (add an item to the end of the list) +// +template +void tsDLList::add (T &item) +{ + tsDLNode &node = item; + + node.pNext = 0; + node.pPrev = this->pLast; + + if (this->itemCount) { + tsDLNode *pLastNode = this->pLast; + pLastNode->pNext = &item; + } + else { + this->pFirst = &item; + } + + this->pLast = &item; + + this->itemCount++; +} + +// +// insertAfter() +// (place item in the list immediately after itemBefore) +// +template +void tsDLList::insertAfter (T &item, T &itemBefore) +{ + tsDLNode &node = item; + tsDLNode &nodeBefore = itemBefore; + + node.pPrev = &itemBefore; + node.pNext = nodeBefore.pNext; + nodeBefore.pNext = &item; + + if (node.pNext) { + tsDLNode *pNextNode = node.pNext; + pNextNode->pPrev = &item; + } + else { + this->pLast = &item; + } + + this->itemCount++; +} + +// +// insertBefore () +// (place item in the list immediately before itemAfter) +// +template +void tsDLList::insertBefore (T &item, T &itemAfter) +{ + tsDLNode &node = item; + tsDLNode &nodeAfter = itemAfter; + + node.pNext = &itemAfter; + node.pPrev = nodeAfter.pPrev; + nodeAfter.pPrev = &item; + + if (node.pPrev) { + tsDLNode *pPrevNode = node.pPrev; + pPrevNode->pNext = &item; + } + else { + this->pFirst = &item; + } + + this->itemCount++; +} + +// +// push () +// (add an item at the beginning of the list) +// +template +void tsDLList::push (T &item) +{ + tsDLNode &node = item; + node.pPrev = 0; + node.pNext = this->pFirst; + + if (this->itemCount) { + tsDLNode *pFirstNode = this->pFirst; + pFirstNode->pPrev = &item; + } + else { + this->pLast = &item; + } + + this->pFirst = &item; + + this->itemCount++; +} + +// +// tsDLIter::next () +// +template +T * tsDLIter::next () +{ + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->pList->pFirst; + } + else { + tsDLNode *pCurNode = pCur; + pCur = pCurNode->pNext; + } + this->pCurrent = pCur; + return pCur; +} + +// +// tsDLIter::prev () +// +template +T * tsDLIter::prev () +{ + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->pList->pLast; + } + else { + tsDLNode *pCurNode = pCur; + pCur = pCurNode->pPrev; + } + this->pCurrent = pCur; + return pCur; +} + +// +// tsDLIter::operator () () +// +template +inline T * tsDLIter::operator () () +{ + return this->next(); +} + +// +// remove () +// remove current item +// (and move current to be the item +// pointed to by pNext - the item seen +// by the iterator before the current one - +// this guarantee that the list will be +// accessed sequentially even if an item +// is removed) +// +template +void tsDLBwdIter::remove () +{ + T *pCur = this->pCurrent; + + if (pCur) { + tsDLNode *pCurNode = pCur; + + // + // strip const (we didnt declare the + // list const in the constructor) + // + tsDLList * pMutableList = + (tsDLList *) this->pList; + + // + // Move this->pCurrent to the item after the + // item being deleted + // + this->pCurrent = pCurNode->pNext; + + // + // delete current item + // + pMutableList->remove(*pCur); + } +} + +// +// tsDLBwdIter::operator () () +// +template +inline T * tsDLBwdIter::operator () () +{ + return this->tsDLIter::prev(); +} + +// +// tsDLBwdIter::prev () +// +template +inline T * tsDLBwdIter::prev () +{ + return this->tsDLIter::prev(); +} + +// +// tsDLFwdIter::remove () +// (and move current to be the item +// pointed to by pPrev - the item seen +// by the iterator before the current one - +// this guarantee that the list will be +// accessed sequentially even if an item +// is removed) +// +template +void tsDLFwdIter::remove () +{ + T *pCur = this->pCurrent; + + if (pCur) { + tsDLNode *pCurNode = pCur; + + // + // Move this->pCurrent to the previous item + // + this->pCurrent = pCurNode->pPrev; + + // + // delete current item + // + this->pList->remove(*pCur); + } +} + +// +// tsDLFwdIter::next () +// +template +inline T * tsDLFwdIter::next () +{ + tsDLIter &iterBase = *this; + return iterBase.next(); +} + +// +// tsDLFwdIter::operator () () +// +template +inline T * tsDLFwdIter::operator () () +{ + return this->next(); +} + +// +// tsDLList::find () // returns -1 if the item isnt on the list // and the node number (beginning with zero if // it is) // template -inline int tsDLList::find(T &item) const +int tsDLList::find(T &item) const { tsDLFwdIter iter(*this); tsDLNode *pItem; diff --git a/src/cxxTemplates/tsSLList.h b/src/cxxTemplates/tsSLList.h index a6e2fba34..dc539bca3 100644 --- a/src/cxxTemplates/tsSLList.h +++ b/src/cxxTemplates/tsSLList.h @@ -31,6 +31,9 @@ * * History * $Log$ + * Revision 1.12 1998/06/16 03:03:07 jhill + * eliminated dangling ptr warning from bounds checker + * * Revision 1.11 1998/05/05 18:06:58 jhill * rearranged to allow compilation by g++ 2.8.1 * @@ -183,22 +186,7 @@ public: // (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if // tsSLNode is always a base class of a T. // - T * next () - { - if (this->pCurrent!=0) { - tsSLNode *pCurNode = this->pCurrent; - this->pCurrent = pCurNode->pNext; - } - else { - const tsSLNode &first = this->list; - // - // assume that we are starting (or restarting) at the - // beginning of the list - // - this->pCurrent = first.pNext; - } - return this->pCurrent; - } + T * next (); // // move iterator forward @@ -245,24 +233,7 @@ public: // (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if // tsSLNode is always a base class of a T. // - T * next () - { - if (this->pCurrent!=0) { - tsSLNode *pCurNode = this->pCurrent; - this->pPrevious = this->pCurrent; - this->pCurrent = pCurNode->pNext; - } - else { - const tsSLNode &first = this->list; - // - // assume that we are starting (or restarting) at the - // beginning of the list - // - this->pCurrent = first.pNext; - this->pPrevious = 0; - } - return this->pCurrent; - } + T * next (); // // move iterator forward @@ -284,29 +255,7 @@ public: // the iterator to the next item. If there is // no current item this function assert fails. // - void remove () - { - assert (this->pCurrent!=0); - - tsSLNode *pPrevNode; - tsSLNode *pCurNode = this->pCurrent; - - if (this->pPrevious==0) { - pPrevNode = &this->list; - // - // this assert fails if it is an attempt to - // delete twice without moving the iterator - // - assert (pPrevNode->pNext == this->pCurrent); - } - else { - pPrevNode = this->pPrevious; - } - - pPrevNode->pNext = pCurNode->pNext; - this->pCurrent = this->pPrevious; - this->pPrevious = 0; - } + void remove (); private: T *pPrevious; @@ -314,3 +263,97 @@ private: tsSLList &list; }; +// +// tsSLIter::next () +// +// move iterator forward +// +// NULL test here is inefficient, but it appears that some architectures +// (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if +// tsSLNode is always a base class of a T. +// +template +T * tsSLIter::next () +{ + if (this->pCurrent!=0) { + tsSLNode *pCurNode = this->pCurrent; + this->pCurrent = pCurNode->pNext; + } + else { + const tsSLNode &first = this->list; + // + // assume that we are starting (or restarting) at the + // beginning of the list + // + this->pCurrent = first.pNext; + } + return this->pCurrent; +} + +// +// tsSLIterRm::next () +// +// move iterator forward +// +// NULL test here is inefficient, but it appears that some architectures +// (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if +// tsSLNode is always a base class of a T. +// +template +T * tsSLIterRm::next () +{ + if (this->pCurrent!=0) { + tsSLNode *pCurNode = this->pCurrent; + this->pPrevious = this->pCurrent; + this->pCurrent = pCurNode->pNext; + } + else { + const tsSLNode &first = this->list; + // + // assume that we are starting (or restarting) at the + // beginning of the list + // + this->pCurrent = first.pNext; + this->pPrevious = 0; + } + return this->pCurrent; +} + +// +// tsSLIterRm::remove () +// +// remove current node +// (and move current to be the previos item - +// the item seen by the iterator before the +// current one - this guarantee that the list +// will be accessed sequentially even if an item +// is removed) +// +// This cant be called twice in a row without moving +// the iterator to the next item. If there is +// no current item this function assert fails. +// +template +void tsSLIterRm::remove () +{ + assert (this->pCurrent!=0); + + tsSLNode *pPrevNode; + tsSLNode *pCurNode = this->pCurrent; + + if (this->pPrevious==0) { + pPrevNode = &this->list; + // + // this assert fails if it is an attempt to + // delete twice without moving the iterator + // + assert (pPrevNode->pNext == this->pCurrent); + } + else { + pPrevNode = this->pPrevious; + } + + pPrevNode->pNext = pCurNode->pNext; + this->pCurrent = this->pPrevious; + this->pPrevious = 0; +} diff --git a/src/libCom/cxxTemplates/resourceLib.h b/src/libCom/cxxTemplates/resourceLib.h index 66a3e8c43..ffe6c8c89 100644 --- a/src/libCom/cxxTemplates/resourceLib.h +++ b/src/libCom/cxxTemplates/resourceLib.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.17 1998/06/16 03:00:19 jhill + * cleaned up fast string hash table + * * Revision 1.16 1998/04/10 23:07:33 jhill * fixed solaris architecture specific problem where xxx>>32 was ignored * @@ -129,14 +132,7 @@ public: int init(unsigned nHashTableEntries); - ~resTable() - { - if (this->pTable) { - this->destroyAllEntries(); - assert (this->nInUse == 0u); - delete [] this->pTable; - } - } + virtual ~resTable(); // // destroy all res in the table @@ -240,6 +236,7 @@ private: class epicsShareClass uintId { public: uintId (unsigned idIn=UINT_MAX) : id(idIn) {} + virtual ~uintId(); int operator == (const uintId &idIn) { @@ -259,38 +256,6 @@ protected: unsigned id; }; -// -// this needs to be instanciated only once (normally in libCom) -// -#ifdef instantiateRecourceLib -// -// uintId::resourceHash() -// -resTableIndex uintId::resourceHash(unsigned /* nBitsId */) const -{ - resTableIndex hashid = this->id; - - // - // This assumes worst case hash table index width of 1 bit. - // We will iterate this loop 5 times on a 32 bit architecture. - // - // A good optimizer will unroll this loop? - // Experiments using the microsoft compiler show that this isnt - // slower than switching on the architecture size and urolling the - // loop explicitly (that solution has resulted in portability - // problems in the past). - // - for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) { - hashid ^= (hashid>>i); - } - - // - // the result here is always masked to the - // proper size after it is returned to the resource class - // - return hashid; -} -#endif // instantiateRecourceLib // // special resource table which uses @@ -302,6 +267,7 @@ template class uintResTable : public resTable { public: uintResTable() : allocId(1u) {} // hashing is faster close to zero + virtual ~uintResTable(); inline void installItem(ITEM &item); private: @@ -316,6 +282,7 @@ class uintRes : public uintId, public tsSLNode { friend class uintResTable; public: uintRes(unsigned idIn=UINT_MAX) : uintId(idIn) {} + virtual ~uintRes(); private: // // workaround for bug in DEC compiler @@ -323,23 +290,6 @@ private: void setId(unsigned newId) {this->id = newId;} }; -// -// uintRes::installItem() -// -// NOTE: This detects (and avoids) the case where -// the PV id wraps around and we attempt to have two -// resources with the same id. -// -template -inline void uintResTable::installItem(ITEM &item) -{ - int resTblStatus; - do { - item.uintRes::setId(allocId++); - resTblStatus = this->add(item); - } - while (resTblStatus); -} // // character string identifier @@ -379,14 +329,7 @@ public: pStr(typeIn==copyString?allocCopyString(idIn):idIn), allocType(typeIn) {} - ~ stringId() - { - if (this->allocType==copyString) { - if (this->pStr!=NULL) { - delete [] (char *) this->pStr; - } - } - } + virtual ~ stringId(); // // The hash algorithm is a modification of the algorithm described in @@ -428,54 +371,6 @@ private: static const unsigned char stringIdFastHash[256]; }; -// -// this needs to be instanciated only once (normally in libCom) -// -#ifdef instantiateRecourceLib -// -// stringId::resourceHash() -// -// The hash algorithm is a modification of the algorithm described in -// Fast Hashing of Variable Length Text Strings, Peter K. Pearson, -// Communications of the ACM, June 1990 -// The modifications were designed by Marty Kraimer -// -resTableIndex stringId::resourceHash(unsigned nBitsId) const -{ - if (this->pStr==NULL) { - return 0u; - } - - unsigned h0 = 0u; - unsigned h1 = 0u; - unsigned c; - unsigned i; - for (i=0u; (c = this->pStr[i]); i++) { - // - // odd - // - if (i&1u) { - h1 = stringIdFastHash[h1 ^ c]; - } - // - // even - // - else { - h0 = stringIdFastHash[h0 ^ c]; - } - } - - // - // does not work well for more than 65k entries ? - // (because some indexes in the table will not be produced) - // - if (nBitsId>=8u) { - h1 = h1 << (nBitsId-8u); - } - return h1 ^ h0; -} -#endif // instantiateRecourceLib - // // resTable::init() // @@ -691,6 +586,165 @@ T *resTable::findDelete (tsSLList &list, const ID &idIn) return pItem; } +// +// ~resTable::resTable() +// +template +resTable::~resTable() +{ + if (this->pTable) { + this->destroyAllEntries(); + assert (this->nInUse == 0u); + delete [] this->pTable; + } +} + +// +// uintResTable::~uintResTable() +// (not inline because it is virtual) +// +template +uintResTable::~uintResTable() {} + +// +// uintRes::~uintRes() +// (not inline because it is virtual) +// +template +uintRes::~uintRes() {} + +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +// +// uintId::resourceHash() +// +resTableIndex uintId::resourceHash(unsigned /* nBitsId */) const +{ + resTableIndex hashid = this->id; + + // + // This assumes worst case hash table index width of 1 bit. + // We will iterate this loop 5 times on a 32 bit architecture. + // + // A good optimizer will unroll this loop? + // Experiments using the microsoft compiler show that this isnt + // slower than switching on the architecture size and urolling the + // loop explicitly (that solution has resulted in portability + // problems in the past). + // + for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) { + hashid ^= (hashid>>i); + } + + // + // the result here is always masked to the + // proper size after it is returned to the resource class + // + return hashid; +} + +// +// uintResTable::~uintResTable() +// (not inline because it is virtual) +// +uintId::~uintId() {} + +#endif // instantiateRecourceLib + +// +// uintRes::installItem() +// +// NOTE: This detects (and avoids) the case where +// the PV id wraps around and we attempt to have two +// resources with the same id. +// +template +inline void uintResTable::installItem(ITEM &item) +{ + int resTblStatus; + do { + item.uintRes::setId(allocId++); + resTblStatus = this->add(item); + } + while (resTblStatus); +} + +// +// stringId::~stringId() +// +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +stringId::~stringId() +{ + if (this->allocType==copyString) { + if (this->pStr!=NULL) { +#ifdef _MSC_VER + // + // bugs in microsloth visual C++ appear to require + // a const cast away here + // + delete [] (char * const) this->pStr; +#else + delete [] this->pStr; +#endif + + } + } +} +#endif // instantiateRecourceLib + +// +// this needs to be instanciated only once (normally in libCom) +// +#ifdef instantiateRecourceLib +// +// stringId::resourceHash() +// +// The hash algorithm is a modification of the algorithm described in +// Fast Hashing of Variable Length Text Strings, Peter K. Pearson, +// Communications of the ACM, June 1990 +// The modifications were designed by Marty Kraimer +// +resTableIndex stringId::resourceHash(unsigned nBitsId) const +{ + if (this->pStr==NULL) { + return 0u; + } + + unsigned h0 = 0u; + unsigned h1 = 0u; + unsigned c; + unsigned i; + for (i=0u; (c = this->pStr[i]); i++) { + // + // odd + // + if (i&1u) { + h1 = stringIdFastHash[h1 ^ c]; + } + // + // even + // + else { + h0 = stringIdFastHash[h0 ^ c]; + } + } + + // + // does not work well for more than 65k entries ? + // (because some indexes in the table will not be produced) + // + if (nBitsId>=8u) { + h1 = h1 << (nBitsId-8u); + } + return h1 ^ h0; +} +#endif // instantiateRecourceLib + // // this needs to be instanciated only once (normally in libCom) // @@ -719,6 +773,7 @@ const unsigned char stringId::stringIdFastHash[256] = { 111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238, 134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47 }; + #endif // instantiateRecourceLib #endif // INCresourceLibh diff --git a/src/libCom/cxxTemplates/tsDLList.h b/src/libCom/cxxTemplates/tsDLList.h index 62fa7032b..1495b6c9b 100644 --- a/src/libCom/cxxTemplates/tsDLList.h +++ b/src/libCom/cxxTemplates/tsDLList.h @@ -31,6 +31,9 @@ * * History * $Log$ + * Revision 1.13 1998/06/16 03:01:44 jhill + * cosmetic + * * Revision 1.12 1998/05/29 17:25:47 jhill * allow use of epicsAssert.h * @@ -151,183 +154,46 @@ public: // adds addList to the end of the list // (and removes all items from addList) // - void add (tsDLList &addList) - { - // - // NOOP if addList is empty - // - if (addList.itemCount==0u) { - return; - } - - if (this->itemCount==0u) { - // - // this is empty so just init from - // addList - // - *this = addList; - } - else { - tsDLNode *pLastNode = this->pLast; - tsDLNode *pAddListFirstNode = addList.pFirst; - - // - // add addList to the end of this - // - pLastNode->pNext = addList.pFirst; - pAddListFirstNode->pPrev = addList.pLast; - this->pLast = addList.pLast; - this->itemCount += addList.itemCount; - } - - // - // leave addList empty - // - addList.clear(); - } + void add (tsDLList &addList); // // add() // (add an item to the end of the list) // - void add (T &item) - { - tsDLNode &node = item; - - node.pNext = 0; - node.pPrev = this->pLast; - - if (this->itemCount) { - tsDLNode *pLastNode = this->pLast; - pLastNode->pNext = &item; - } - else { - this->pFirst = &item; - } - - this->pLast = &item; - - this->itemCount++; - } + void add (T &item); // // get () // - T * get() - { - T *pItem = this->pFirst; - - if (pItem) { - this->remove (*pItem); - } - - return pItem; - } + T * get(); // // insertAfter() // (place item in the list immediately after itemBefore) // - void insertAfter (T &item, T &itemBefore) - { - tsDLNode &node = item; - tsDLNode &nodeBefore = itemBefore; - - node.pPrev = &itemBefore; - node.pNext = nodeBefore.pNext; - nodeBefore.pNext = &item; - - if (node.pNext) { - tsDLNode *pNextNode = node.pNext; - pNextNode->pPrev = &item; - } - else { - this->pLast = &item; - } - - this->itemCount++; - } + void insertAfter (T &item, T &itemBefore); // // insertBefore () // (place item in the list immediately before itemAfter) // - void insertBefore (T &item, T &itemAfter) - { - tsDLNode &node = item; - tsDLNode &nodeAfter = itemAfter; - - node.pNext = &itemAfter; - node.pPrev = nodeAfter.pPrev; - nodeAfter.pPrev = &item; - - if (node.pPrev) { - tsDLNode *pPrevNode = node.pPrev; - pPrevNode->pNext = &item; - } - else { - this->pFirst = &item; - } - - this->itemCount++; - } + void insertBefore (T &item, T &itemAfter); // // remove () // - void remove (T &item) - { - tsDLNode &node = item; - - if (this->pLast == &item) { - this->pLast = node.pPrev; - } - else { - tsDLNode *pNextNode = node.pNext; - pNextNode->pPrev = node.pPrev; - } - - if (this->pFirst == &item) { - this->pFirst = node.pNext; - } - else { - tsDLNode *pPrevNode = node.pPrev; - pPrevNode->pNext = node.pNext; - } - - this->itemCount--; - } + void remove (T &item); // // pop () // (returns the first item on the list) - T * pop() - { - return this->get(); - } + T * pop(); // // push () // (add an item at the beginning of the list) // - void push (T &item) - { - tsDLNode &node = item; - node.pPrev = 0; - node.pNext = this->pFirst; - - if (this->itemCount) { - tsDLNode *pFirstNode = this->pFirst; - pFirstNode->pPrev = &item; - } - else { - this->pLast = &item; - } - - this->pFirst = &item; - - this->itemCount++; - } + void push (T &item); // // find @@ -364,6 +230,7 @@ private: tsDLList (const tsDLList &); }; + // // tsDLIterBD // (a bi-directional iterator in the style of the STL) @@ -377,8 +244,7 @@ public: tsDLIterBD (T *pInitialEntry) : pEntry(pInitialEntry) {} - tsDLIterBD (class tsDLIterBD ©In) : - pEntry(copyIn.pEntry) {} + tsDLIterBD (const class tsDLIterBD ©In); tsDLIterBD & operator = (T *pNewEntry) { @@ -459,7 +325,7 @@ public: private: T *pEntry; }; - + // // tsDLIter // @@ -474,7 +340,7 @@ private: template class tsDLIter { public: - tsDLIter (const tsDLList & listIn) : + tsDLIter (tsDLList & listIn) : pCurrent(0), pList(&listIn) {} void reset () @@ -493,33 +359,9 @@ public: this->reset(listIn); } - T * next () - { - T *pCur = this->pCurrent; - if (pCur==0) { - pCur = this->pList->pFirst; - } - else { - tsDLNode *pCurNode = pCur; - pCur = pCurNode->pNext; - } - this->pCurrent = pCur; - return pCur; - } + T * next (); - T * prev () - { - T *pCur = this->pCurrent; - if (pCur==0) { - pCur = this->pList->pLast; - } - else { - tsDLNode *pCurNode = pCur; - pCur = pCurNode->pPrev; - } - this->pCurrent = pCur; - return pCur; - } + T * prev (); T * first() { @@ -533,14 +375,11 @@ public: return this->pCurrent; } - T * operator () () - { - return this->next(); - } + T * operator () (); protected: T *pCurrent; - const tsDLList *pList; + tsDLList *pList; }; // @@ -561,30 +400,28 @@ protected: template class tsDLFwdIter: private tsDLIter { public: - tsDLFwdIter (const tsDLList &listIn) : + tsDLFwdIter (tsDLList &listIn) : tsDLIter(listIn) {} void reset () { this->tsDLIter::reset(); } + void reset (tsDLList &listIn) { this->tsDLIter::reset(listIn); } + void operator = (tsDLList &listIn) { this->tsDLIter::reset(listIn); } - T * operator () () - { - return this->tsDLIter::next(); - } - T * next () - { - tsDLIter &iterBase = *this; - return iterBase.next(); - } + + T * operator () (); + + T * next (); + T * first() { tsDLIter &iterBase = *this; @@ -600,31 +437,7 @@ public: // accessed sequentially even if an item // is removed) // - void remove () - { - T *pCur = this->pCurrent; - - if (pCur) { - tsDLNode *pCurNode = pCur; - - // - // strip const (we didnt declare the - // list const in the constructor) - // - tsDLList * pMutableList = - (tsDLList *) this->pList; - - // - // Move this->pCurrent to the previous item - // - this->pCurrent = pCurNode->pPrev; - - // - // delete current item - // - pMutableList->remove(*pCur); - } - } + void remove (); }; // @@ -645,29 +458,28 @@ public: template class tsDLBwdIter : private tsDLIter { public: - tsDLBwdIter(const tsDLList &listIn) : + tsDLBwdIter(tsDLList &listIn) : tsDLIter(listIn) {} void reset () { this->tsDLIter::reset(); } + void reset (tsDLList &listIn) { this->tsDLIter::reset(listIn); } + void operator = (tsDLList &listIn) { this->tsDLIter::reset(listIn); } - T * operator () () - { - return this->tsDLIter::prev(); - } - T * prev () - { - return this->tsDLIter::prev(); - } + + T * operator () (); + + T * prev (); + T * last() { return this->tsDLIter::last(); @@ -683,43 +495,366 @@ public: // accessed sequentially even if an item // is removed) // - void remove () - { - T *pCur = this->pCurrent; - - if (pCur) { - tsDLNode *pCurNode = pCur; - - // - // strip const (we didnt declare the - // list const in the constructor) - // - tsDLList * pMutableList = - (tsDLList *) this->pList; - - // - // Move this->pCurrent to the item after the - // item being deleted - // - this->pCurrent = pCurNode->pNext; - - // - // delete current item - // - pMutableList->remove(*pCur); - } - } + void remove (); }; +// +// MS Visual C 6.0 requires that this code is not provided in +// the class definition because the class isnt fully defined yet +// +template +inline tsDLIterBD::tsDLIterBD(const class tsDLIterBD ©In) : + pEntry(copyIn.pEntry) {} + // -// find +// tsDLList::remove () +// +template +void tsDLList::remove (T &item) +{ + tsDLNode &node = item; + + if (this->pLast == &item) { + this->pLast = node.pPrev; + } + else { + tsDLNode *pNextNode = node.pNext; + pNextNode->pPrev = node.pPrev; + } + + if (this->pFirst == &item) { + this->pFirst = node.pNext; + } + else { + tsDLNode *pPrevNode = node.pPrev; + pPrevNode->pNext = node.pNext; + } + + this->itemCount--; +} + +// +// tsDLList::get () +// +template +inline T * tsDLList::get() +{ + T *pItem = this->pFirst; + + if (pItem) { + this->remove (*pItem); + } + + return pItem; +} + +// +// tsDLList::pop () +// (returns the first item on the list) +template +inline T * tsDLList::pop() +{ + return this->get(); +} + +// +// add() - +// adds addList to the end of the list +// (and removes all items from addList) +// +template +void tsDLList::add (tsDLList &addList) +{ + // + // NOOP if addList is empty + // + if (addList.itemCount==0u) { + return; + } + + if (this->itemCount==0u) { + // + // this is empty so just init from + // addList + // + *this = addList; + } + else { + tsDLNode *pLastNode = this->pLast; + tsDLNode *pAddListFirstNode = addList.pFirst; + + // + // add addList to the end of this + // + pLastNode->pNext = addList.pFirst; + pAddListFirstNode->pPrev = addList.pLast; + this->pLast = addList.pLast; + this->itemCount += addList.itemCount; + } + + // + // leave addList empty + // + addList.clear(); +} + +// +// add() +// (add an item to the end of the list) +// +template +void tsDLList::add (T &item) +{ + tsDLNode &node = item; + + node.pNext = 0; + node.pPrev = this->pLast; + + if (this->itemCount) { + tsDLNode *pLastNode = this->pLast; + pLastNode->pNext = &item; + } + else { + this->pFirst = &item; + } + + this->pLast = &item; + + this->itemCount++; +} + +// +// insertAfter() +// (place item in the list immediately after itemBefore) +// +template +void tsDLList::insertAfter (T &item, T &itemBefore) +{ + tsDLNode &node = item; + tsDLNode &nodeBefore = itemBefore; + + node.pPrev = &itemBefore; + node.pNext = nodeBefore.pNext; + nodeBefore.pNext = &item; + + if (node.pNext) { + tsDLNode *pNextNode = node.pNext; + pNextNode->pPrev = &item; + } + else { + this->pLast = &item; + } + + this->itemCount++; +} + +// +// insertBefore () +// (place item in the list immediately before itemAfter) +// +template +void tsDLList::insertBefore (T &item, T &itemAfter) +{ + tsDLNode &node = item; + tsDLNode &nodeAfter = itemAfter; + + node.pNext = &itemAfter; + node.pPrev = nodeAfter.pPrev; + nodeAfter.pPrev = &item; + + if (node.pPrev) { + tsDLNode *pPrevNode = node.pPrev; + pPrevNode->pNext = &item; + } + else { + this->pFirst = &item; + } + + this->itemCount++; +} + +// +// push () +// (add an item at the beginning of the list) +// +template +void tsDLList::push (T &item) +{ + tsDLNode &node = item; + node.pPrev = 0; + node.pNext = this->pFirst; + + if (this->itemCount) { + tsDLNode *pFirstNode = this->pFirst; + pFirstNode->pPrev = &item; + } + else { + this->pLast = &item; + } + + this->pFirst = &item; + + this->itemCount++; +} + +// +// tsDLIter::next () +// +template +T * tsDLIter::next () +{ + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->pList->pFirst; + } + else { + tsDLNode *pCurNode = pCur; + pCur = pCurNode->pNext; + } + this->pCurrent = pCur; + return pCur; +} + +// +// tsDLIter::prev () +// +template +T * tsDLIter::prev () +{ + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->pList->pLast; + } + else { + tsDLNode *pCurNode = pCur; + pCur = pCurNode->pPrev; + } + this->pCurrent = pCur; + return pCur; +} + +// +// tsDLIter::operator () () +// +template +inline T * tsDLIter::operator () () +{ + return this->next(); +} + +// +// remove () +// remove current item +// (and move current to be the item +// pointed to by pNext - the item seen +// by the iterator before the current one - +// this guarantee that the list will be +// accessed sequentially even if an item +// is removed) +// +template +void tsDLBwdIter::remove () +{ + T *pCur = this->pCurrent; + + if (pCur) { + tsDLNode *pCurNode = pCur; + + // + // strip const (we didnt declare the + // list const in the constructor) + // + tsDLList * pMutableList = + (tsDLList *) this->pList; + + // + // Move this->pCurrent to the item after the + // item being deleted + // + this->pCurrent = pCurNode->pNext; + + // + // delete current item + // + pMutableList->remove(*pCur); + } +} + +// +// tsDLBwdIter::operator () () +// +template +inline T * tsDLBwdIter::operator () () +{ + return this->tsDLIter::prev(); +} + +// +// tsDLBwdIter::prev () +// +template +inline T * tsDLBwdIter::prev () +{ + return this->tsDLIter::prev(); +} + +// +// tsDLFwdIter::remove () +// (and move current to be the item +// pointed to by pPrev - the item seen +// by the iterator before the current one - +// this guarantee that the list will be +// accessed sequentially even if an item +// is removed) +// +template +void tsDLFwdIter::remove () +{ + T *pCur = this->pCurrent; + + if (pCur) { + tsDLNode *pCurNode = pCur; + + // + // Move this->pCurrent to the previous item + // + this->pCurrent = pCurNode->pPrev; + + // + // delete current item + // + this->pList->remove(*pCur); + } +} + +// +// tsDLFwdIter::next () +// +template +inline T * tsDLFwdIter::next () +{ + tsDLIter &iterBase = *this; + return iterBase.next(); +} + +// +// tsDLFwdIter::operator () () +// +template +inline T * tsDLFwdIter::operator () () +{ + return this->next(); +} + +// +// tsDLList::find () // returns -1 if the item isnt on the list // and the node number (beginning with zero if // it is) // template -inline int tsDLList::find(T &item) const +int tsDLList::find(T &item) const { tsDLFwdIter iter(*this); tsDLNode *pItem; diff --git a/src/libCom/cxxTemplates/tsSLList.h b/src/libCom/cxxTemplates/tsSLList.h index a6e2fba34..dc539bca3 100644 --- a/src/libCom/cxxTemplates/tsSLList.h +++ b/src/libCom/cxxTemplates/tsSLList.h @@ -31,6 +31,9 @@ * * History * $Log$ + * Revision 1.12 1998/06/16 03:03:07 jhill + * eliminated dangling ptr warning from bounds checker + * * Revision 1.11 1998/05/05 18:06:58 jhill * rearranged to allow compilation by g++ 2.8.1 * @@ -183,22 +186,7 @@ public: // (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if // tsSLNode is always a base class of a T. // - T * next () - { - if (this->pCurrent!=0) { - tsSLNode *pCurNode = this->pCurrent; - this->pCurrent = pCurNode->pNext; - } - else { - const tsSLNode &first = this->list; - // - // assume that we are starting (or restarting) at the - // beginning of the list - // - this->pCurrent = first.pNext; - } - return this->pCurrent; - } + T * next (); // // move iterator forward @@ -245,24 +233,7 @@ public: // (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if // tsSLNode is always a base class of a T. // - T * next () - { - if (this->pCurrent!=0) { - tsSLNode *pCurNode = this->pCurrent; - this->pPrevious = this->pCurrent; - this->pCurrent = pCurNode->pNext; - } - else { - const tsSLNode &first = this->list; - // - // assume that we are starting (or restarting) at the - // beginning of the list - // - this->pCurrent = first.pNext; - this->pPrevious = 0; - } - return this->pCurrent; - } + T * next (); // // move iterator forward @@ -284,29 +255,7 @@ public: // the iterator to the next item. If there is // no current item this function assert fails. // - void remove () - { - assert (this->pCurrent!=0); - - tsSLNode *pPrevNode; - tsSLNode *pCurNode = this->pCurrent; - - if (this->pPrevious==0) { - pPrevNode = &this->list; - // - // this assert fails if it is an attempt to - // delete twice without moving the iterator - // - assert (pPrevNode->pNext == this->pCurrent); - } - else { - pPrevNode = this->pPrevious; - } - - pPrevNode->pNext = pCurNode->pNext; - this->pCurrent = this->pPrevious; - this->pPrevious = 0; - } + void remove (); private: T *pPrevious; @@ -314,3 +263,97 @@ private: tsSLList &list; }; +// +// tsSLIter::next () +// +// move iterator forward +// +// NULL test here is inefficient, but it appears that some architectures +// (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if +// tsSLNode is always a base class of a T. +// +template +T * tsSLIter::next () +{ + if (this->pCurrent!=0) { + tsSLNode *pCurNode = this->pCurrent; + this->pCurrent = pCurNode->pNext; + } + else { + const tsSLNode &first = this->list; + // + // assume that we are starting (or restarting) at the + // beginning of the list + // + this->pCurrent = first.pNext; + } + return this->pCurrent; +} + +// +// tsSLIterRm::next () +// +// move iterator forward +// +// NULL test here is inefficient, but it appears that some architectures +// (intel) dont like to cast a NULL pointer from a tsSLNode to a T even if +// tsSLNode is always a base class of a T. +// +template +T * tsSLIterRm::next () +{ + if (this->pCurrent!=0) { + tsSLNode *pCurNode = this->pCurrent; + this->pPrevious = this->pCurrent; + this->pCurrent = pCurNode->pNext; + } + else { + const tsSLNode &first = this->list; + // + // assume that we are starting (or restarting) at the + // beginning of the list + // + this->pCurrent = first.pNext; + this->pPrevious = 0; + } + return this->pCurrent; +} + +// +// tsSLIterRm::remove () +// +// remove current node +// (and move current to be the previos item - +// the item seen by the iterator before the +// current one - this guarantee that the list +// will be accessed sequentially even if an item +// is removed) +// +// This cant be called twice in a row without moving +// the iterator to the next item. If there is +// no current item this function assert fails. +// +template +void tsSLIterRm::remove () +{ + assert (this->pCurrent!=0); + + tsSLNode *pPrevNode; + tsSLNode *pCurNode = this->pCurrent; + + if (this->pPrevious==0) { + pPrevNode = &this->list; + // + // this assert fails if it is an attempt to + // delete twice without moving the iterator + // + assert (pPrevNode->pNext == this->pCurrent); + } + else { + pPrevNode = this->pPrevious; + } + + pPrevNode->pNext = pCurNode->pNext; + this->pCurrent = this->pPrevious; + this->pPrevious = 0; +}