//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  Copyright (C) Microsoft Corporation, 1990 - 1999
//
//  File:       linklist.hxx
//
//--------------------------------------------------------------------------

/* --------------------------------------------------------------------

                      Microsoft OS/2 LAN Manager
                   Copyright(c) Microsoft Corp., 1990

                  RPC locator - Written by Steven Zeck


        This file contains a linked list class definition.
        This base class for Link and Item just contains a set of
        two pointers.   Derived classes are created with the
        macros LinkList or LinkListClass (used for nested inheritance).
        These derived classes take your member data items and add them
        to the base class.

        If you define a macro ASSERT_VCLASS/ASSERT_CLASS, then you must
        define a member method Assert for each class you derived which checks
        the runtime data consistance of the members you have added.
-------------------------------------------------------------------- */

#ifndef _LINKLIST_
#define _LINKLIST_

#ifndef ASSERT_VCLASS
#define ASSERT_CLASS void Assert() {(void)(0);}
#define ASSERT_VCLASS ASSERT_CLASS
#endif

class LinkItem {                        // Linked list Item (LI) class *&

private:

        LinkItem *pLINext;              // Next and Previous Nodes
        LinkItem *pLIPrev;

public:
        friend class LinkList;
        ASSERT_VCLASS;

        LinkItem *Next(                 // return the Next element on the list
        ) {
            return (pLINext);
        }

        void Remove(LinkList& pLLHead); // delete a LI from a LinkList
};

class LinkList {                        // A Linked List (LL) class *&

        friend class LinkItem;

private:

        LinkItem *pLIHead;              // Head of list
        LinkItem *pLITail;              // Tail of list

public:

        ASSERT_CLASS;

        LinkList(                       // constructure for a new LL
        ) {
            pLIHead = pLITail = Nil;
        }

        void Add(LinkItem *pLInew);     // Add new item item at head of list
        void Append(LinkItem *pLInew);  // Append new item item at end of list

        LinkItem *First(                // return the First element on the list
        ) {
             this->Assert();
             return (pLIHead);
        }
};

// This macro is used to dervive a linked list from an existing class
// This is a way to do multiple inheritance before C++ 2.0

#define LINK_LIST_DERVIVED(CLASS, DERVIVED, MEMBERS)            \
                                                                \
class CLASS: public DERVIVED {                                  \
                                                                \
private:                                                        \
        CLASS *pLINext;                                         \
        CLASS *pLIPrev;                                         \
                                                                \
        MEMBERS                                                 \
public:                                                         \
        friend class CLASS##List;                               \
        ASSERT_VCLASS;                                          \
                                                                \
        CLASS *Next(                                            \
        ) {                                                     \
	     return ((pLINext)? (CLASS *) ((char *)pLINext -	\
                    (int) &(((CLASS *) 0)->pLINext) ): Nil);    \
	 }							 \
                                                                \
        void Remove(CLASS##List& pLLHead) {                     \
            ((LinkItem *)(&this->pLINext))->LinkItem::Remove(*(LinkList *) &pLLHead);           \
        }                                                       \
};                                                              \
                                                                \
class CLASS##List {                                             \
                                                                \
        friend class CLASS;                                     \
                                                                \
private:                                                        \
                                                                \
        CLASS *pLIHead;                                         \
        CLASS *pLITail;                                         \
public:                                                         \
                                                                \
        ASSERT_CLASS;                                           \
                                                                \
        CLASS##List(                                            \
        ) {                                                     \
            pLIHead = pLITail = Nil;                            \
        }                                                       \
                                                                \
        CLASS * Add(CLASS *pLInew) {                            \
            ((LinkList *)(&this->pLIHead))->Add((LinkItem *) &pLInew->pLINext);  \
            return(pLInew);                                     \
        }                                                       \
        CLASS * Append(CLASS *pLInew) {                         \
            ((LinkList *)(&this->pLIHead))->Append((LinkItem *) &pLInew->pLINext); \
            return(pLInew);                                     \
        }                                                       \
                                                                \
        CLASS *First(                                           \
        ) {                                                     \
             this->Assert();                                    \
             return ((pLIHead)? (CLASS *) ((char *)pLIHead -    \
                    (int) &(((CLASS *) 0)->pLINext) ): Nil);    \
        }                                                       \
};                                                              \

#define ToItem(TYPE, arg) ((TYPE##Item *) ((char *)arg-sizeof(LinkList)))

// Include NIL_NEW, if you want Add/Append with default NEW constructors

#define NIL_NEW                                                 \
                                                                \
        CLASS_PREFIX##Item  *Add() {                            \
                                                                \
            CLASS_PREFIX##Item *pLLI = new CLASS_PREFIX##Item;  \
            if (pLLI != 0)                                      \
                LinkList::Add(pLLI);                            \
            return (pLLI);                                      \
        }                                                       \
                                                                \
                                                                \
        CLASS_PREFIX##Item  *Append() {                         \
                                                                \
            CLASS_PREFIX##Item *pLLI = new CLASS_PREFIX##Item;  \
            if (pLLI != 0)                                      \
                LinkList::Append(pLLI);                         \
            return (pLLI);                                      \
        }                                                       \
                                                                \

//** This macro defines a instance of a linklist item **//

#define LINK_LIST(CLASS_PREFIX, MEMBERS) LINK_LIST_CLASS(CLASS_PREFIX, Link, MEMBERS)

#define LINK_LIST_CLASS(CLASS_PREFIX, BASE, MEMBERS)            \
                                                                \
class CLASS_PREFIX##List;                                       \
                                                                \
class CLASS_PREFIX##Item:public BASE##Item {                    \
                                                                \
public:                                                         \
                                                                \
        CLASS_PREFIX##Item *Next(                               \
        ) {                                                     \
            this->Assert();                                     \
            return ((CLASS_PREFIX##Item *)(this->LinkItem::Next())); \
        }                                                       \
                                                                \
        /* Put an ASSERT_VCLASS in MEMBERS if desired */        \
                                                                \
        MEMBERS                                                 \
                                                                \
};                                                              \
                                                                \
class CLASS_PREFIX##List:public BASE##List {                    \
                                                                \
public:                                                         \
                                                                \
        CLASS_PREFIX##Item  *Add(CLASS_PREFIX##Item *pLLI) {    \
                                                                \
            LinkList::Add(pLLI);                                \
            return (pLLI);                                      \
        }                                                       \
                                                                \
        CLASS_PREFIX##Item  *Append(CLASS_PREFIX##Item *pLLI) { \
                                                                \
            LinkList::Append(pLLI);                             \
            return (pLLI);                                      \
        }                                                       \
                                                                \
                                                                \
        CLASS_PREFIX##Item *First(                              \
        ) {                                                     \
            return ((CLASS_PREFIX##Item *)LinkList::First());   \
        }                                                       \
                                                                \
                                                                \
};

#endif // _LINKLIST_