/****************************************************************************/ /** Microsoft OS/2 LAN Manager **/ /** Copyright(c) Microsoft Corp., 1990 **/ /****************************************************************************/ /****************************************************************************\ dlist.hxx LM 3.0 Generic dlist packackage This header file contains a generic dlist macro that can be used to create an efficient doubly linked list implementation for any type. USAGE: class DUMB { [...] public: int Compare( const DUMB * pd ) { return (( _i == pd->_i ) ? 0 : (( _i < pd->_i ) ? -1 : 1 ) ) ; } [...] } ; DECLARE_DLIST_OF(DUMB) // or DECLARE_EXT_DLIST_OF(DUMB) DLIST_OF(DUMB) dumDlist ; ITER_DL_OF( DUMB ) iterDum( dumDlist ) ; RITER_DL_OF(DUMB ) riterDum(dumDlist ) ; main() { dumDlist.Add( new DUMB( SomeData ) ) ; while ( ( pd = iterDum.Next() ) != NULL ) pd->DoSomething() ; } SUGGESTIONS FOR MODIFICATION: FILE HISTORY: johnl 23-Jul-1990 Created johnl 16-Oct-1990 Changes as per Peterwi's requests johnl 31-Oct-1990 Updated to reflect new iter. functionality johnl 7-Mar-1991 Code review changes KeithMo 23-Oct-1991 Added forward references. \****************************************************************************/ #ifndef _DLIST_HXX_ #define _DLIST_HXX_ // DebugPrint() declaration macro. #if defined(DEBUG) #define DBG_PRINT_DLIST_IMPLEMENTATION { _DebugPrint(); } #else #define DBG_PRINT_DLIST_IMPLEMENTATION { ; } #endif #define DECLARE_DBG_PRINT_DLIST \ void _DebugPrint () const ; \ void DebugPrint () const DBG_PRINT_DLIST_IMPLEMENTATION // // Forward references. // DLL_CLASS DL_NODE; DLL_CLASS ITER_DL; DLL_CLASS ITER_L; DLL_CLASS DLIST; DLL_CLASS RITER_DL; /****************************************************************************\ * *NAME DL_NODE * *WORKBOOK: DL_NODE * *SYNOPSIS: Storage class for the DLIST type * \****************************************************************************/ DLL_CLASS DL_NODE { friend class ITER_DL ; public: DL_NODE( DL_NODE *Prev, DL_NODE *Next, void * pelem ) { Set( Prev, Next, pelem ) ; } void Set( DL_NODE *Prev, DL_NODE *Next, void * pelem ) { _pelem = pelem ; _pdlnodeNext = Next ; _pdlnodePrev = Prev ; } DL_NODE *_pdlnodeNext, *_pdlnodePrev ; /* Links in DLIST */ void *_pelem ; /* Pointer to element */ } ; /****************************************************************************\ * *NAME: ITER_L * *WORKBOOK: ITER_L * *SYNOPSIS: Abstract list iterator class for ITER_DL & RITER_DL * *INTERFACE: void * vNext() - Returns the next item or NULL * *NOTES: This guy was created so some code for ITER_DL & RITER_DL * could be shared (that polymorphous thang). We couldn't use * the ITER defn. from iter.hxx because of the semi-parameterized * nature of the DLIST class (see discussion under ITER_DL). * * C++ doesn't allow you to overload on the return type of a method. * Ideally, what we would want is (in an inheritance tree): * * 0. ITER_L ( void * vNext() ) * 1. ITER_DL RITER_DL ( void * vNext() ) * 2. ITER_DL_JUNK RITER_DL_JUNK ( JUNK *Next() ) * * The user would then be free to create ITER_L *'s and treat all * ITERs in the same way. The generic approach however requires * the upper levels of the tree (Level 1) to operate with void * pointers, thus when you try and parametrize the virtual method * and tell it to return a JUNK * (as opposed to a void *) the * compiler complains because the return type for the virtual * method is different. Thus in this interface, the virtual * method is called vNext (which returns a void *), and is cast * to the appropriate parameterized type at level 2. You could * use the virtual method vNext if you needed to mix iterators * and cast it yourself. We are not publicizing this use however * because it probably will not occur. * * The _pdlnodeCurrent always points to an slist node except when * the list is empty or the iterator is at the end of the list. * * The _fUsed member is a flag which tells the iterator whether or * not to go to the next node (it doesn't move till it has been * used once, thus the name _fUsed). * *HISTORY: johnl 25-jul-90 Created * * * \****************************************************************************/ DLL_CLASS ITER_L { friend class DLIST ; public: virtual void* vNext( void ) = 0 ; void * QueryProp( void ) { return (_pdlnodeCurrent != NULL ? _pdlnodeCurrent->_pelem : NULL ) ; } protected: DL_NODE * _pdlnodeCurrent ; /* Pointer to current node */ DLIST * _pdlist ; /* Pointer to DLIST this iter belongs */ BOOL _fUsed ; /* Has been used flag */ ITER_L * _pdliterNext ; }; /****************************************************************************\ * *NAME: ITER_DL * *WORKBOOK: ITER_DL, RITER_DL * *SYNOPSIS: Forward/Reverse iterator for the DLIST class * The iterator "points" to the element that was just returned by * vNext. *INTERFACE: * ITER_DL( ) - Constructor * ITER_DL( ) - Contructor w/ no position at iterdl * ~ITER_DL() ; - Destructor * void Reset( ) - Reset the iterator to its initial state * void* operator()() - Synonym for next * void* vNext( ) ; - Goto the next element in the list * void* QueryProp( )- Returns the current property this iterator * is pointing to * *PARENT: * *USES: * *CAVEATS: Even though ITER_L is a base object, you cannot create an array * of ITER * and use this interface. See NOTES below. * *HISTORY: johnl 07-25-90 Created * \****************************************************************************/ DLL_CLASS ITER_DL : public ITER_L { friend class DLIST ; friend class ITER_DL ; public: ITER_DL( DLIST * pdl ) ; ITER_DL( const ITER_DL& iterdl ) ; ~ITER_DL() ; void Reset( void ) ; void* vNext( void ) ; }; DLL_CLASS RITER_DL : public ITER_L { friend class DLIST ; friend class RITER_DL ; public: RITER_DL( DLIST * pdl ) ; RITER_DL( const RITER_DL& riterdl ) ; ~RITER_DL() ; void Reset( void ) ; void* vNext( void ) ; }; /****************************************************************************\ * *NAME: DLIST * *WORKBOOK: DLIST * *SYNOPSIS: Parameterized DLIST implementation * *INTERFACE: DECLARE_DLIST_OF() - Produces a declaration for a dlist * of itemtype. * * DECLARE_EXT_DLIST_OF() - Produces a declaration for a dlist * of itemtype, with the addition of * a couple more methods (Remove, IsMember) * * DLIST_OF() dlMylist ;- Declares a dlist of itemtype called * dlMylist * * ITER_DL_OF(itemtype) iterdlType() ; * - Declares a forward iterator for dlMyList * * ITER_DL_OF(itemtype) iterdlType() ; * - Declares forward iterator at the passed * iterator * * RITER_DL_OF(itemtype) riterdlType() ; * - Declares a reverse iterator for dlMyList * * RITER_DL_OF(itemtype) riterdlType() ; * - Declares a reverse iterator at the passed * iterator * * Clear() - Specifically delete all elements in the * dlist (code is in macro expansion) * * QueryNumElem( ) - Returns the number of elements * in the dlist. * * Add( ) - Makes a copy of element e * and adds it as the next element in the dlist. * * Append( ) - Makes a copy of element e * and adds it at the end of the dlist. * * Insert( ) - Makes a copy of element e and adds it to the * "left" of the passed iterator. * * Remove( ) - Removes the element to the left of * the passed iter and returns the element. * * * Remove( ) - Finds element e and * removes it from the list, returning the item. * (only defined when using DECLARE_EXT_DLIST_OF()) * * IsMember( ) - Returns true if the element belongs to the * dlist. * (only defined when using DECLARE_EXT_DLIST_OF()) * * * private: * * BumpIters( ) - For any iterators pointing to the passed * iter node, BumpIters calls iter.Next(). Used when deleting * an item from the list. * * Register( ) - Registers an iterator with the dlist * * Deregister( ) - Deregisters an iterator with the dlist * * SetIters( ) - Sets all registered iters to the * passed value. * * Unlink() - Removes the passed DL_NODE from the dlist. Returns * the properties pointer or NULL if not found. The * DL_NODE is deleted. * * *PARENT: LIST * *USES: * *CAVEATS: * *HISTORY: * Johnl 28-Jun-1990 Created * Johnl 12-Jul-1990 Made iters safe for deleting * Johnl 16-Oct-1990 Moved Clear to macro expansion * (so it can access dest. of object) * KeithMo 09-Oct-1991 Win32 Conversion. * \****************************************************************************/ DLL_CLASS DLIST { friend class ITER_DL ; friend class RITER_DL ; public: DLIST( ) ; ~DLIST() ; // void Clear( void ) ; <<-- Defined in macro expansion UINT QueryNumElem( void ) ; APIERR Add( void * pelem ) ; APIERR Append( void * pelem ) ; APIERR Insert( void * pelem, ITER_DL& dliter ) ; APIERR Insert( void * pelem, RITER_DL& dlriter ) ; void * Remove( ITER_DL& dliter ) ; void * Remove( RITER_DL& dlriter ) ; DECLARE_DBG_PRINT_DLIST protected: DL_NODE *_pdlHead, *_pdlTail ; /* Head and Tail of DLIST */ ITER_L *_pdliterRegisteredIters ; /* Pointer to list of registered iters. */ protected: void Register( ITER_L * pdliter ) ; void Deregister( ITER_L * pdliter ) ; void BumpIters( DL_NODE *pdlnode ) ; void SetIters( DL_NODE *pdlnode ) ; BOOL CheckIter( ITER_L *pdliter ) ; void * Unlink( DL_NODE * pdlnodeTarget ) ; } ; /**********************************************************************\ NAME: DECLARE_DLIST_OF( type ) SYNOPSIS: Macro that expands into the type specific portions of the DLIST package. The difference between DECLARE_DLIST_OF and DECLARE_EXT_DLIST_OF is that DECLARE_EXT_DLIST_OF defines additional methods. Specifically: Remove( ) - Find and remove element e from the dlist IsMember( ) - Returns TRUE if item e is in the dlist NOTES: Other helper macros are: DLIST_OF( type ) - for declaring DLIST lists ITER_DL_OF(type) - for declaring Forward iterators RITER_DL_OF(type) - for declaring reverse iterators See the beginning of this file for usage of this package. HISTORY: johnl 24-Jul-90 Created johnl 15-Oct-90 Broke out Remove & IsMember to be conditional on the symbol EXTENDED_DL \**********************************************************************/ #define DLIST_OF(type) DLIST_OF_##type #define ITER_DL_OF(type) ITER_DL_##type #define RITER_DL_OF(type) RITER_DL_##type #define DECL_DLIST_OF(type,dec) \ class dec DLIST_OF(type) ; \ \ class dec ITER_DL_OF(type) : public ITER_DL \ { \ public: \ ITER_DL_OF(type)( DLIST& dl ) : ITER_DL(&dl) { ; } \ ITER_DL_OF(type)( const ITER_DL_OF(type)& iterdl ) \ : ITER_DL(iterdl ) { ; } \ ~ITER_DL_OF(type)() { ; } \ \ inline type* Next( void ) \ { \ return (type *)ITER_DL::vNext() ; \ } \ inline type* operator()(void) { return (type *) Next(); } \ \ inline type* QueryProp( void ) { return (type *)ITER_L::QueryProp() ; } \ }; \ \ class dec RITER_DL_OF(type) : public RITER_DL \ { \ public: \ RITER_DL_OF(type)( DLIST& dl ) : RITER_DL(&dl) { ; } \ RITER_DL_OF(type)( const RITER_DL_OF(type)& riterdl ) \ : RITER_DL(riterdl) { ; } \ ~RITER_DL_OF(type)() { ; } \ \ inline type* Next( void ) \ { \ return (type *)RITER_DL::vNext() ; \ } \ inline type* operator()(void) { return (type *) Next(); } \ \ inline type* QueryProp( void ) { return (type *)ITER_L::QueryProp() ; } \ \ }; \ \ class dec DLIST_OF(type) : public DLIST \ { \ private: \ BOOL _fDestroy; \ \ public: \ DLIST_OF(type) ( BOOL fDestroy = TRUE ) \ : _fDestroy( fDestroy ) \ { ; } \ ~DLIST_OF(type)() { Clear() ; } \ \ void Clear( void ) \ { \ register DL_NODE *_pdlnode = _pdlHead, *_pdlnodeOld = NULL ; \ \ while ( _pdlnode != NULL ) \ { \ _pdlnodeOld = _pdlnode ; \ _pdlnode = _pdlnode->_pdlnodeNext ; \ if ( _fDestroy ) \ delete ((type *)_pdlnodeOld->_pelem) ; \ delete _pdlnodeOld ; \ } \ _pdlHead = _pdlTail = NULL ; \ \ SetIters( NULL ) ; \ } \ \ \ inline APIERR Add( type* const pelem ) \ { \ return DLIST::Add( (void *)pelem ) ; \ } \ \ inline APIERR Append( type* const pelem ) \ { \ return DLIST::Append( (void *)pelem ) ; \ } \ \ inline APIERR Insert( type * pelem, ITER_DL_OF(type)& dliter ) \ { \ return DLIST::Insert( (void *)pelem, dliter ) ; \ } \ \ inline APIERR Insert( type* pelem, RITER_DL_OF(type)& riterdl ) \ { \ return DLIST::Insert( (void *)pelem, riterdl ) ; \ } \ \ inline type* Remove( ITER_DL_OF(type)& iterdl ) \ { \ return (type *) DLIST::Remove( iterdl ) ; \ } \ \ inline type* Remove( RITER_DL_OF(type)& riterdl ) \ { \ return (type *) DLIST::Remove( riterdl ) ; \ } \ \ /* The following can only be used if you use the extended DLIST */ \ type* Remove( const type& e ) ; \ BOOL IsMember( const type& e ) ; \ \ } ; //DECLARE_DLIST_OF(type) #define DECL_EXT_DLIST_OF(type,dec) \ DECL_DLIST_OF(type,dec) \ type * DLIST_OF(type)::Remove( const type& e ) \ { \ register DL_NODE *_pdlnode = _pdlHead ; \ \ while ( _pdlnode != NULL ) \ { \ if ( !((type *)_pdlnode->_pelem)->Compare( &e ) ) \ return (type *) Unlink( _pdlnode ) ; \ else \ _pdlnode = _pdlnode->_pdlnodeNext ; \ } \ \ return (type *) NULL ; \ } \ \ BOOL DLIST_OF(type)::IsMember( const type& e ) \ { \ register DL_NODE *_pdlnode = _pdlHead ; \ \ while ( _pdlnode != NULL ) \ { \ if ( !((type *)_pdlnode->_pelem)->Compare( &e ) ) \ return TRUE ; \ else \ _pdlnode = _pdlnode->_pdlnodeNext ; \ } \ \ return FALSE ; \ } // Helper macros for code preservation #define DECLARE_DLIST_OF(type) \ DECL_DLIST_OF(type,DLL_TEMPLATE) #define DECLARE_EXT_DLIST_OF(type) \ DECL_EXT_DLIST_OF(type,DLL_TEMPLATE) #endif // _DLIST_HXX_