attempted to clean up HP-UX warnings
This commit is contained in:
@@ -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 ITEM>
|
||||
class uintResTable : public resTable<ITEM, uintId> {
|
||||
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<ITEM> {
|
||||
friend class uintResTable<ITEM>;
|
||||
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<ITEM>::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 <class ITEM>
|
||||
inline void uintResTable<ITEM>::installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintRes<ITEM>::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<T,ID>::init()
|
||||
//
|
||||
@@ -691,6 +586,165 @@ T *resTable<T,ID>::findDelete (tsSLList<T> &list, const ID &idIn)
|
||||
return pItem;
|
||||
}
|
||||
|
||||
//
|
||||
// ~resTable<T,ID>::resTable()
|
||||
//
|
||||
template <class T, class ID>
|
||||
resTable<T,ID>::~resTable()
|
||||
{
|
||||
if (this->pTable) {
|
||||
this->destroyAllEntries();
|
||||
assert (this->nInUse == 0u);
|
||||
delete [] this->pTable;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// uintResTable<ITEM>::~uintResTable()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
template <class ITEM>
|
||||
uintResTable<ITEM>::~uintResTable() {}
|
||||
|
||||
//
|
||||
// uintRes<ITEM>::~uintRes()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
template <class ITEM>
|
||||
uintRes<ITEM>::~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<ITEM>::~uintResTable()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
uintId::~uintId() {}
|
||||
|
||||
#endif // instantiateRecourceLib
|
||||
|
||||
//
|
||||
// uintRes<ITEM>::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 <class ITEM>
|
||||
inline void uintResTable<ITEM>::installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintRes<ITEM>::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
|
||||
|
||||
@@ -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<T> &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<T> *pLastNode = this->pLast;
|
||||
tsDLNode<T> *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<T> &addList);
|
||||
|
||||
//
|
||||
// add()
|
||||
// (add an item to the end of the list)
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
node.pNext = 0;
|
||||
node.pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
tsDLNode<T> &nodeBefore = itemBefore;
|
||||
|
||||
node.pPrev = &itemBefore;
|
||||
node.pNext = nodeBefore.pNext;
|
||||
nodeBefore.pNext = &item;
|
||||
|
||||
if (node.pNext) {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
tsDLNode<T> &nodeAfter = itemAfter;
|
||||
|
||||
node.pNext = &itemAfter;
|
||||
node.pPrev = nodeAfter.pPrev;
|
||||
nodeAfter.pPrev = &item;
|
||||
|
||||
if (node.pPrev) {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
void insertBefore (T &item, T &itemAfter);
|
||||
|
||||
//
|
||||
// remove ()
|
||||
//
|
||||
void remove (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = node.pPrev;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = node.pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = node.pNext;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
node.pPrev = 0;
|
||||
node.pNext = this->pFirst;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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<T>
|
||||
// (a bi-directional iterator in the style of the STL)
|
||||
@@ -377,8 +244,7 @@ public:
|
||||
tsDLIterBD (T *pInitialEntry) :
|
||||
pEntry(pInitialEntry) {}
|
||||
|
||||
tsDLIterBD (class tsDLIterBD<T> ©In) :
|
||||
pEntry(copyIn.pEntry) {}
|
||||
tsDLIterBD (const class tsDLIterBD<T> ©In);
|
||||
|
||||
tsDLIterBD<T> & operator = (T *pNewEntry)
|
||||
{
|
||||
@@ -459,7 +325,7 @@ public:
|
||||
private:
|
||||
T *pEntry;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// tsDLIter<T>
|
||||
//
|
||||
@@ -474,7 +340,7 @@ private:
|
||||
template <class T>
|
||||
class tsDLIter {
|
||||
public:
|
||||
tsDLIter (const tsDLList<T> & listIn) :
|
||||
tsDLIter (tsDLList<T> & 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<T> *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<T> *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<T> *pList;
|
||||
tsDLList<T> *pList;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -561,30 +400,28 @@ protected:
|
||||
template <class T>
|
||||
class tsDLFwdIter: private tsDLIter<T> {
|
||||
public:
|
||||
tsDLFwdIter (const tsDLList<T> &listIn) :
|
||||
tsDLFwdIter (tsDLList<T> &listIn) :
|
||||
tsDLIter<T>(listIn) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->tsDLIter<T>::reset();
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
T * operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::next();
|
||||
}
|
||||
T * next ()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
return iterBase.next();
|
||||
}
|
||||
|
||||
T * operator () ();
|
||||
|
||||
T * next ();
|
||||
|
||||
T * first()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
@@ -600,31 +437,7 @@ public:
|
||||
// accessed sequentially even if an item
|
||||
// is removed)
|
||||
//
|
||||
void remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) 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 T>
|
||||
class tsDLBwdIter : private tsDLIter<T> {
|
||||
public:
|
||||
tsDLBwdIter(const tsDLList<T> &listIn) :
|
||||
tsDLBwdIter(tsDLList<T> &listIn) :
|
||||
tsDLIter<T>(listIn) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->tsDLIter<T>::reset();
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
T * operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
T * prev ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
T * operator () ();
|
||||
|
||||
T * prev ();
|
||||
|
||||
T * last()
|
||||
{
|
||||
return this->tsDLIter<T>::last();
|
||||
@@ -683,43 +495,366 @@ public:
|
||||
// accessed sequentially even if an item
|
||||
// is removed)
|
||||
//
|
||||
void remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) 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 <class T>
|
||||
inline tsDLIterBD<T>::tsDLIterBD(const class tsDLIterBD<T> ©In) :
|
||||
pEntry(copyIn.pEntry) {}
|
||||
|
||||
|
||||
//
|
||||
// find
|
||||
// tsDLList<T>::remove ()
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::remove (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = node.pPrev;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = node.pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = node.pNext;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = node.pNext;
|
||||
}
|
||||
|
||||
this->itemCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::get ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLList<T>::get()
|
||||
{
|
||||
T *pItem = this->pFirst;
|
||||
|
||||
if (pItem) {
|
||||
this->remove (*pItem);
|
||||
}
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::pop ()
|
||||
// (returns the first item on the list)
|
||||
template <class T>
|
||||
inline T * tsDLList<T>::pop()
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
|
||||
//
|
||||
// add() -
|
||||
// adds addList to the end of the list
|
||||
// (and removes all items from addList)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::add (tsDLList<T> &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<T> *pLastNode = this->pLast;
|
||||
tsDLNode<T> *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 <class T>
|
||||
void tsDLList<T>::add (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
node.pNext = 0;
|
||||
node.pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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 <class T>
|
||||
void tsDLList<T>::insertAfter (T &item, T &itemBefore)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
tsDLNode<T> &nodeBefore = itemBefore;
|
||||
|
||||
node.pPrev = &itemBefore;
|
||||
node.pNext = nodeBefore.pNext;
|
||||
nodeBefore.pNext = &item;
|
||||
|
||||
if (node.pNext) {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// insertBefore ()
|
||||
// (place item in the list immediately before itemAfter)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::insertBefore (T &item, T &itemAfter)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
tsDLNode<T> &nodeAfter = itemAfter;
|
||||
|
||||
node.pNext = &itemAfter;
|
||||
node.pPrev = nodeAfter.pPrev;
|
||||
nodeAfter.pPrev = &item;
|
||||
|
||||
if (node.pPrev) {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// push ()
|
||||
// (add an item at the beginning of the list)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::push (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
node.pPrev = 0;
|
||||
node.pNext = this->pFirst;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *pFirstNode = this->pFirst;
|
||||
pFirstNode->pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->pFirst = &item;
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::next ()
|
||||
//
|
||||
template <class T>
|
||||
T * tsDLIter<T>::next ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->pList->pFirst;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
pCur = pCurNode->pNext;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::prev ()
|
||||
//
|
||||
template <class T>
|
||||
T * tsDLIter<T>::prev ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->pList->pLast;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
pCur = pCurNode->pPrev;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLIter<T>::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 <class T>
|
||||
void tsDLBwdIter<T>::remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) this->pList;
|
||||
|
||||
//
|
||||
// Move this->pCurrent to the item after the
|
||||
// item being deleted
|
||||
//
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
|
||||
//
|
||||
// delete current item
|
||||
//
|
||||
pMutableList->remove(*pCur);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLBwdIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLBwdIter<T>::operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLBwdIter<T>::prev ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLBwdIter<T>::prev ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::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 <class T>
|
||||
void tsDLFwdIter<T>::remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// Move this->pCurrent to the previous item
|
||||
//
|
||||
this->pCurrent = pCurNode->pPrev;
|
||||
|
||||
//
|
||||
// delete current item
|
||||
//
|
||||
this->pList->remove(*pCur);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::next ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLFwdIter<T>::next ()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
return iterBase.next();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLFwdIter<T>::operator () ()
|
||||
{
|
||||
return this->next();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::find ()
|
||||
// returns -1 if the item isnt on the list
|
||||
// and the node number (beginning with zero if
|
||||
// it is)
|
||||
//
|
||||
template <class T>
|
||||
inline int tsDLList<T>::find(T &item) const
|
||||
int tsDLList<T>::find(T &item) const
|
||||
{
|
||||
tsDLFwdIter<T> iter(*this);
|
||||
tsDLNode<T> *pItem;
|
||||
|
||||
@@ -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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
T * next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
T * next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pPrevious = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T> *pPrevNode;
|
||||
tsSLNode<T> *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<T> &list;
|
||||
};
|
||||
|
||||
//
|
||||
// tsSLIter<T>::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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
template <class T>
|
||||
T * tsSLIter<T>::next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &first = this->list;
|
||||
//
|
||||
// assume that we are starting (or restarting) at the
|
||||
// beginning of the list
|
||||
//
|
||||
this->pCurrent = first.pNext;
|
||||
}
|
||||
return this->pCurrent;
|
||||
}
|
||||
|
||||
//
|
||||
// tsSLIterRm<T>::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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
template <class T>
|
||||
T * tsSLIterRm<T>::next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pPrevious = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T>::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 <class T>
|
||||
void tsSLIterRm<T>::remove ()
|
||||
{
|
||||
assert (this->pCurrent!=0);
|
||||
|
||||
tsSLNode<T> *pPrevNode;
|
||||
tsSLNode<T> *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;
|
||||
}
|
||||
|
||||
@@ -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 ITEM>
|
||||
class uintResTable : public resTable<ITEM, uintId> {
|
||||
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<ITEM> {
|
||||
friend class uintResTable<ITEM>;
|
||||
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<ITEM>::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 <class ITEM>
|
||||
inline void uintResTable<ITEM>::installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintRes<ITEM>::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<T,ID>::init()
|
||||
//
|
||||
@@ -691,6 +586,165 @@ T *resTable<T,ID>::findDelete (tsSLList<T> &list, const ID &idIn)
|
||||
return pItem;
|
||||
}
|
||||
|
||||
//
|
||||
// ~resTable<T,ID>::resTable()
|
||||
//
|
||||
template <class T, class ID>
|
||||
resTable<T,ID>::~resTable()
|
||||
{
|
||||
if (this->pTable) {
|
||||
this->destroyAllEntries();
|
||||
assert (this->nInUse == 0u);
|
||||
delete [] this->pTable;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// uintResTable<ITEM>::~uintResTable()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
template <class ITEM>
|
||||
uintResTable<ITEM>::~uintResTable() {}
|
||||
|
||||
//
|
||||
// uintRes<ITEM>::~uintRes()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
template <class ITEM>
|
||||
uintRes<ITEM>::~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<ITEM>::~uintResTable()
|
||||
// (not inline because it is virtual)
|
||||
//
|
||||
uintId::~uintId() {}
|
||||
|
||||
#endif // instantiateRecourceLib
|
||||
|
||||
//
|
||||
// uintRes<ITEM>::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 <class ITEM>
|
||||
inline void uintResTable<ITEM>::installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintRes<ITEM>::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
|
||||
|
||||
@@ -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<T> &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<T> *pLastNode = this->pLast;
|
||||
tsDLNode<T> *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<T> &addList);
|
||||
|
||||
//
|
||||
// add()
|
||||
// (add an item to the end of the list)
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
node.pNext = 0;
|
||||
node.pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
tsDLNode<T> &nodeBefore = itemBefore;
|
||||
|
||||
node.pPrev = &itemBefore;
|
||||
node.pNext = nodeBefore.pNext;
|
||||
nodeBefore.pNext = &item;
|
||||
|
||||
if (node.pNext) {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
tsDLNode<T> &nodeAfter = itemAfter;
|
||||
|
||||
node.pNext = &itemAfter;
|
||||
node.pPrev = nodeAfter.pPrev;
|
||||
nodeAfter.pPrev = &item;
|
||||
|
||||
if (node.pPrev) {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
void insertBefore (T &item, T &itemAfter);
|
||||
|
||||
//
|
||||
// remove ()
|
||||
//
|
||||
void remove (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = node.pPrev;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = node.pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = node.pNext;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *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<T> &node = item;
|
||||
node.pPrev = 0;
|
||||
node.pNext = this->pFirst;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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<T>
|
||||
// (a bi-directional iterator in the style of the STL)
|
||||
@@ -377,8 +244,7 @@ public:
|
||||
tsDLIterBD (T *pInitialEntry) :
|
||||
pEntry(pInitialEntry) {}
|
||||
|
||||
tsDLIterBD (class tsDLIterBD<T> ©In) :
|
||||
pEntry(copyIn.pEntry) {}
|
||||
tsDLIterBD (const class tsDLIterBD<T> ©In);
|
||||
|
||||
tsDLIterBD<T> & operator = (T *pNewEntry)
|
||||
{
|
||||
@@ -459,7 +325,7 @@ public:
|
||||
private:
|
||||
T *pEntry;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// tsDLIter<T>
|
||||
//
|
||||
@@ -474,7 +340,7 @@ private:
|
||||
template <class T>
|
||||
class tsDLIter {
|
||||
public:
|
||||
tsDLIter (const tsDLList<T> & listIn) :
|
||||
tsDLIter (tsDLList<T> & 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<T> *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<T> *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<T> *pList;
|
||||
tsDLList<T> *pList;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -561,30 +400,28 @@ protected:
|
||||
template <class T>
|
||||
class tsDLFwdIter: private tsDLIter<T> {
|
||||
public:
|
||||
tsDLFwdIter (const tsDLList<T> &listIn) :
|
||||
tsDLFwdIter (tsDLList<T> &listIn) :
|
||||
tsDLIter<T>(listIn) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->tsDLIter<T>::reset();
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
T * operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::next();
|
||||
}
|
||||
T * next ()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
return iterBase.next();
|
||||
}
|
||||
|
||||
T * operator () ();
|
||||
|
||||
T * next ();
|
||||
|
||||
T * first()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
@@ -600,31 +437,7 @@ public:
|
||||
// accessed sequentially even if an item
|
||||
// is removed)
|
||||
//
|
||||
void remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) 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 T>
|
||||
class tsDLBwdIter : private tsDLIter<T> {
|
||||
public:
|
||||
tsDLBwdIter(const tsDLList<T> &listIn) :
|
||||
tsDLBwdIter(tsDLList<T> &listIn) :
|
||||
tsDLIter<T>(listIn) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->tsDLIter<T>::reset();
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->tsDLIter<T>::reset(listIn);
|
||||
}
|
||||
T * operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
T * prev ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
T * operator () ();
|
||||
|
||||
T * prev ();
|
||||
|
||||
T * last()
|
||||
{
|
||||
return this->tsDLIter<T>::last();
|
||||
@@ -683,43 +495,366 @@ public:
|
||||
// accessed sequentially even if an item
|
||||
// is removed)
|
||||
//
|
||||
void remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) 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 <class T>
|
||||
inline tsDLIterBD<T>::tsDLIterBD(const class tsDLIterBD<T> ©In) :
|
||||
pEntry(copyIn.pEntry) {}
|
||||
|
||||
|
||||
//
|
||||
// find
|
||||
// tsDLList<T>::remove ()
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::remove (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = node.pPrev;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = node.pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = node.pNext;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = node.pNext;
|
||||
}
|
||||
|
||||
this->itemCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::get ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLList<T>::get()
|
||||
{
|
||||
T *pItem = this->pFirst;
|
||||
|
||||
if (pItem) {
|
||||
this->remove (*pItem);
|
||||
}
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::pop ()
|
||||
// (returns the first item on the list)
|
||||
template <class T>
|
||||
inline T * tsDLList<T>::pop()
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
|
||||
//
|
||||
// add() -
|
||||
// adds addList to the end of the list
|
||||
// (and removes all items from addList)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::add (tsDLList<T> &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<T> *pLastNode = this->pLast;
|
||||
tsDLNode<T> *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 <class T>
|
||||
void tsDLList<T>::add (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
|
||||
node.pNext = 0;
|
||||
node.pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *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 <class T>
|
||||
void tsDLList<T>::insertAfter (T &item, T &itemBefore)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
tsDLNode<T> &nodeBefore = itemBefore;
|
||||
|
||||
node.pPrev = &itemBefore;
|
||||
node.pNext = nodeBefore.pNext;
|
||||
nodeBefore.pNext = &item;
|
||||
|
||||
if (node.pNext) {
|
||||
tsDLNode<T> *pNextNode = node.pNext;
|
||||
pNextNode->pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// insertBefore ()
|
||||
// (place item in the list immediately before itemAfter)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::insertBefore (T &item, T &itemAfter)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
tsDLNode<T> &nodeAfter = itemAfter;
|
||||
|
||||
node.pNext = &itemAfter;
|
||||
node.pPrev = nodeAfter.pPrev;
|
||||
nodeAfter.pPrev = &item;
|
||||
|
||||
if (node.pPrev) {
|
||||
tsDLNode<T> *pPrevNode = node.pPrev;
|
||||
pPrevNode->pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// push ()
|
||||
// (add an item at the beginning of the list)
|
||||
//
|
||||
template <class T>
|
||||
void tsDLList<T>::push (T &item)
|
||||
{
|
||||
tsDLNode<T> &node = item;
|
||||
node.pPrev = 0;
|
||||
node.pNext = this->pFirst;
|
||||
|
||||
if (this->itemCount) {
|
||||
tsDLNode<T> *pFirstNode = this->pFirst;
|
||||
pFirstNode->pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->pFirst = &item;
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::next ()
|
||||
//
|
||||
template <class T>
|
||||
T * tsDLIter<T>::next ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->pList->pFirst;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
pCur = pCurNode->pNext;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::prev ()
|
||||
//
|
||||
template <class T>
|
||||
T * tsDLIter<T>::prev ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->pList->pLast;
|
||||
}
|
||||
else {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
pCur = pCurNode->pPrev;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLIter<T>::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 <class T>
|
||||
void tsDLBwdIter<T>::remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// strip const (we didnt declare the
|
||||
// list const in the constructor)
|
||||
//
|
||||
tsDLList<T> * pMutableList =
|
||||
(tsDLList<T> *) this->pList;
|
||||
|
||||
//
|
||||
// Move this->pCurrent to the item after the
|
||||
// item being deleted
|
||||
//
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
|
||||
//
|
||||
// delete current item
|
||||
//
|
||||
pMutableList->remove(*pCur);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLBwdIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLBwdIter<T>::operator () ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLBwdIter<T>::prev ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLBwdIter<T>::prev ()
|
||||
{
|
||||
return this->tsDLIter<T>::prev();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::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 <class T>
|
||||
void tsDLFwdIter<T>::remove ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
|
||||
if (pCur) {
|
||||
tsDLNode<T> *pCurNode = pCur;
|
||||
|
||||
//
|
||||
// Move this->pCurrent to the previous item
|
||||
//
|
||||
this->pCurrent = pCurNode->pPrev;
|
||||
|
||||
//
|
||||
// delete current item
|
||||
//
|
||||
this->pList->remove(*pCur);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::next ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLFwdIter<T>::next ()
|
||||
{
|
||||
tsDLIter<T> &iterBase = *this;
|
||||
return iterBase.next();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLFwdIter<T>::operator () ()
|
||||
//
|
||||
template <class T>
|
||||
inline T * tsDLFwdIter<T>::operator () ()
|
||||
{
|
||||
return this->next();
|
||||
}
|
||||
|
||||
//
|
||||
// tsDLList<T>::find ()
|
||||
// returns -1 if the item isnt on the list
|
||||
// and the node number (beginning with zero if
|
||||
// it is)
|
||||
//
|
||||
template <class T>
|
||||
inline int tsDLList<T>::find(T &item) const
|
||||
int tsDLList<T>::find(T &item) const
|
||||
{
|
||||
tsDLFwdIter<T> iter(*this);
|
||||
tsDLNode<T> *pItem;
|
||||
|
||||
@@ -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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
T * next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
T * next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pPrevious = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T> *pPrevNode;
|
||||
tsSLNode<T> *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<T> &list;
|
||||
};
|
||||
|
||||
//
|
||||
// tsSLIter<T>::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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
template <class T>
|
||||
T * tsSLIter<T>::next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &first = this->list;
|
||||
//
|
||||
// assume that we are starting (or restarting) at the
|
||||
// beginning of the list
|
||||
//
|
||||
this->pCurrent = first.pNext;
|
||||
}
|
||||
return this->pCurrent;
|
||||
}
|
||||
|
||||
//
|
||||
// tsSLIterRm<T>::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<T> to a T even if
|
||||
// tsSLNode<T> is always a base class of a T.
|
||||
//
|
||||
template <class T>
|
||||
T * tsSLIterRm<T>::next ()
|
||||
{
|
||||
if (this->pCurrent!=0) {
|
||||
tsSLNode<T> *pCurNode = this->pCurrent;
|
||||
this->pPrevious = this->pCurrent;
|
||||
this->pCurrent = pCurNode->pNext;
|
||||
}
|
||||
else {
|
||||
const tsSLNode<T> &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<T>::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 <class T>
|
||||
void tsSLIterRm<T>::remove ()
|
||||
{
|
||||
assert (this->pCurrent!=0);
|
||||
|
||||
tsSLNode<T> *pPrevNode;
|
||||
tsSLNode<T> *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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user