/* CSList.H : C++ template for single linked lists * * Implementation is based on Stroustrup 'The C++ Prog Language' * Section 8.3 * * Intrusive (Data contains next field) and Non-intrusive lists * are possible. Iterators are available. */ #ifndef _CSLIST_H_ #define _CSLIST_H_ #include #include /*** Forward declarations ***/ class CSList_Base_Iter; template class CISList_Iter; template class CTSList_Iter; /*** Definition of the links in the lists ***/ /* Class for a link in the list */ class CISLink { public: CISLink *m_Next; /*** Methods ***/ CISLink() { m_Next = NULL; } CISLink(CISLink *p) { m_Next = p; } }; /* Class for a link in the non-intrusive list */ template class CTSLink : public CISLink { public: T m_Data; /*** Methods ***/ /* Use initialiser to avoid default construction & assignment */ CTSLink(const T& data) : m_Data(data) { } }; /*** Definition of the base list class ***/ /* This class must not be used directly ! * Use derived classes CSList and CTSList instead * * Implementation uses a circular list */ class CSList_Base { private: /* Pointer to last element in the (circular) list */ CISLink *m_Last; /*** Methods ***/ public: void Add(CISLink *link); void Append(CISLink *link); CISLink *Remove(); void Clear() { m_Last = NULL; } CSList_Base() { m_Last = NULL; } CSList_Base(CISLink *link) { m_Last = link->m_Next = link; } friend class CSList_Base_Iter; }; /* Implementation of base functions */ inline void CSList_Base::Add(CISLink *data) { // Add an element to the head of the list if(m_Last != NULL) { // Not empty data->m_Next = m_Last->m_Next; } else { m_Last = data; } m_Last->m_Next = data; } inline void CSList_Base::Append(CISLink *data) { if(m_Last != NULL) { data->m_Next = m_Last->m_Next; m_Last = m_Last->m_Next = data; } else { m_Last = data->m_Next = data; } } /*** Definition & Implementation of an intrusive list ***/ template class CISList : private CSList_Base { public: void Add(T* data) { CSList_Base::Add(data); } void Append(T* data) { CSList_Base::Append(data); } T* Remove() { return (T*) CSList_Base::Remove(); } void Clear() { CSList_Base::Clear(); } friend class CISList_Iter; }; /*** Definition & Implementation of a non-intrusive list ***/ template class CTSList : protected CSList_Base { public: void Add(const T& data); void Append(const T& data); T Remove(); void RemoveAll(); void Clear() { CSList_Base::Clear(); } friend class CTSList_Iter; }; template inline void CTSList::Add(const T& data) { CSList_Base::Add(new CTSLink(data)); } template inline void CTSList::Append(const T& data) { CSList_Base::Append(new CTSLink(data)); } template inline T CTSList::Remove() { CTSLink* link = (CTSLink *)CSList_Base::Remove(); if(link != NULL) { T data = link->m_Data; delete link; return data; } else { /* TODO : real exeption handling */ T def; return(def); } } template inline void CTSList::RemoveAll() { CTSLink* link = (CTSLink *)CSList_Base::Remove(); while(link != NULL) { delete link; link = (CTSLink *)CSList_Base::Remove(); } } /*** Iterators for the different list classes ***/ /* For the base class - don't use directly */ class CSList_Base_Iter { private: CISLink* m_CurrentElement; CSList_Base* m_CurrentList; public: inline CSList_Base_Iter(CSList_Base& list); inline CISLink* Next(void); inline void Init(CSList_Base& list); }; inline void CSList_Base_Iter::Init(CSList_Base& list) { m_CurrentList = &list; m_CurrentElement = m_CurrentList->m_Last; } inline CSList_Base_Iter::CSList_Base_Iter(CSList_Base& list) { Init(list); } inline CISLink* CSList_Base_Iter::Next(void) { CISLink *ret = (m_CurrentElement ? (m_CurrentElement=m_CurrentElement->m_Next) : (CISLink *)NULL); if(m_CurrentElement == m_CurrentList->m_Last) { m_CurrentElement = NULL; } return ret; } /* For the intrusive list */ template class CISList_Iter : private CSList_Base_Iter { public: CISList_Iter(CISList& list) : CSList_Base_Iter(list) {} T* Next(void) { return (T*) CSList_Base_Iter::Next(); } void Init(CISList& list) {CSList_Base_Iter::Init(list); } }; /* For the non-intrusive list */ template class CTSList_Iter : private CSList_Base_Iter { public: CTSList_Iter(CTSList& list) : CSList_Base_Iter(list) {} inline T* Next(void); inline void Init(CTSList& list); }; template inline T* CTSList_Iter::Next(void) { CTSLink* link = (CTSLink*) CSList_Base_Iter::Next(); return (link ? &link->m_Data : (T*)NULL); } template inline void CTSList_Iter::Init(CTSList& list) { CSList_Base_Iter::Init(list); } #endif /* _CSLIST_H_ */