name: DoubleLinkedList<class TObject> : public DstrBase;
synopsis:

>     g++ [flags ...] file ...

>     #include <DoubleLinkedList.h>

>     DoubleLinkedList(ALLOCATION alloc_d = DEF_ALLOCATION);
>     boolean insert(TObject* item);
>     boolean insertFirst(TObject* item);
>     boolean removeLast(TObject*& item);
>     const TObject* getPrev() const;

quick start:

>     // declare a character list and add two characters into it
>     //
>     DoubleLinkedList<Char> list;
>     Char item0(L'a');
>     Char item1(L'b');
>     list.insertFirst(&item0);
>     list.insert(&item1);

>     // get the last character
>     //
>     list.gotoLast();
>     Char* item2 = list.getCurr();
>     if (item2->ne(item1)) {
>        // error
>     }

description:
The DoubleLinkedList class, as its name suggests is a list template class that supports list processing using a data structure that contains a pointer to the next and previous elements in the list. (A single linked list, by constrast, contains a pointer only to the next node). For a good reference on lists, see:

T. Budd, Data Structures in C++ using the Standard Template Library, Addison Wesley, Reading, Massachusetts, USA, pp. 185-216, 1998.

The user may select the memory management mode in which this class operates: USER or SYSTEM. In SYSTEM mode, the class is responsible for managing the memory for the objects it contains. This implies that a copy is made each time an object is inserted to the list. In USER mode the user is responsible for allocation and deletion of the objects that are stored in the list. In this mode, pointers to the external objects are stored - a copy is not made. The best mode for your application depends on your need to trade-off speed versus the complexity of object management.
dependencies:

- DstrBase
- DoubleLinkedNode
- VectorLong
- String
- Char
- Long
- Console
- Stack

public constants:

- define the class name:

      static const String CLASS_NAME = L"DoubleLinkedList";

- i/o related constants:

      static const String DEF_PARAM = L"values";

error codes:

- general DoubleLinkedList class error:

      static const long ERR = 40400;

protected data:

- define the NODE object

      typedef DoubleLinkedNode<TObject> NODE;

- pointers to the first node, last node and current node:

      NODE* first_d;

      NODE* last_d;

      NODE* curr_d;

- a pointer to a node the user marks:

      NODE* mark_d;

- the number of nodes in the list:

      Long length_d;

- the allocation mode:

      ALLOCATION alloc_d;

- declare the debugging parameters:

      static Integral::DEBUG debug_level_d;

- static memory manager:

      static MemoryManager mgr_d;

required public methods:

- static methods: diagnose method is moved outside the class header file and defined in the DoubleLinkedListDiagnose.h in order to avoid issues with the preprocessing of the diagnose code

      static const String& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      static boolean setDebug(Integral::DEBUG debug_level);

      boolean debug(const unichar* message) const;

- destructor/constructor(s):

      ~DoubleLinkedList();

      DoubleLinkedList(ALLOCATION alloc = DEF_ALLOCATION);

      DoubleLinkedList(const DoubleLinkedList<TObject>& copy_list);

- assign methods:

      boolean assign(const DoubleLinkedList<TObject>& copy_list);

- operator= methods:

      DoubleLinkedList<TObject>& operator=(const DoubleLinkedList<TObject>& arg);

- equality methods:

      boolean eq(const DoubleLinkedList<TObject>& compare_list) const;

- i/o methods: refer to the notes section for an explanation of why there are two read and write methods in this class

      long sofSize() const;

      boolean read(Sof& sof, long tag);

      boolean write(Sof& sof, long tag) const;

      boolean read(Sof& sof, long tag, const String& name);

      boolean write(Sof& sof, long tag, const String& name) const;

      boolean readData(Sof& sof, const String& pname = DEF_PARAM, long size = SofParser::FULL_OBJECT, boolean param_a = true, boolean nested_a = false);

      boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

- memory management methods:

      static void* operator new(size_t size);

      static void* operator new[](size_t size);

      static void operator delete(void* ptr);

      static void operator delete[](void* ptr);

      static boolean setGrowSize(long grow_size);

      boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE);

class-specific public methods:

- overloaded operators and extensions to required methods:

      TObject& operator() (long index);

      const TObject& operator() (long index) const;

      boolean ne(const DoubleLinkedList<TObject>& compare_list) const;

- class positioning methods:

      boolean gotoFirst();

      boolean gotoLast();

      boolean gotoNext();

      boolean gotoPrev();

      boolean gotoMark();

      boolean gotoPosition(long number);

      long getPosition() const;

- class marking methods:

      boolean markIsSet() const;

      boolean isMarkedElement() const;

      boolean clearMark() const;

      boolean setMark() const;

- class access methods:

      TObject* getFirst();

      const TObject* getFirst() const;

      TObject* getLast();

      const TObject* getLast() const;

      TObject* getNext();

      const TObject* getNext() const;

      TObject* getPrev();

      const TObject* getPrev() const;

      TObject* getMark();

      const TObject* getMark() const;

      TObject* getCurr();

      const TObject* getCurr() const;

- class insert and remove methods:

      boolean insert(TObject* item);

      boolean insert(DoubleLinkedList<TObject>& ilist);

      boolean remove(TObject*& item);

      boolean remove();

      boolean insertFirst(TObject* item);

      boolean insertFirst(DoubleLinkedList<TObject>& ilist);

      boolean removeFirst(TObject*& item);

      boolean removeFirst();

      boolean insertLast(DoubleLinkedList<TObject>& ilist);

      boolean removeLast(TObject*& item);

      boolean removeLast();

- class property methods:

      boolean isEmpty() const;

      boolean isFirst() const;

      boolean isLast() const;

      long length() const;

      boolean find(const TObject* item);

      boolean contains(const TObject* item) const;

- class ordering methods:

      boolean sort(Integral::ORDER sort_order = Integral::ASCENDING, SORT_ALGO = DEF_SORT_ALGO);

      boolean reverse();

      boolean swap(long i, long j);

- class apply methods:

      boolean apply(boolean (TObject::*method)());

      boolean apply(boolean (TObject::*method)(), DoubleLinkedList<TObject>& arg);

- class allocation mode methods:

      ALLOCATION getAllocationMode() const;

      boolean setAllocationMode(ALLOCATION alloc);

private methods:

- sort methods:

      boolean randQuickSort(Integral::ORDER sort_order);

      boolean insertionSort(Integral::ORDER sort_order);

- swap methods:

      boolean swap(NODE*& i_node, NODE*& j_node);

- node addressing methods:

      NODE* getNode(long index) const;

friend classes:

    friend class DoubleLinkedListDiagnose;

examples:

- This example shows the basic operation of a DoubleLinkedList

      #include <DoubleLinkedList.h>
      #include <Char.h>

      int main() {

        // local variables
        //
        DoubleLinkedList<Long> d;
        Long j;

        // add 10 items to the DoubleLinkedList
        //
        for (long i = 0; i< 10; i++) {
          j = i * 3;
          d.insert(&j);
        }

        // see what is on the DoubleLinkedList
        //
        d.debug(L"after insertion");

        // get the elements and print them
        //
        d.gotoFirst();
        Long* l = d.getFirst();
        l->debug(L"item from the List");

        while((l=d.getNext())!=NULL) {
          d.gotoNext();
          l->debug(L"item from the List");
        }

        // exit gracefully
        //
        Integral::exit();
      }

- This example shows the basic operation of a DoubleLinkedList in USER mode. Note that memory is manually allocated before inserting it to the List and deleted later.

      #include <DoubleLinkedList.h>
      #include <Char.h>

      int main() {

        // local variables
        //
        DoubleLinkedList<long> d(USER);
        Long* j;

        // add 10 items to the DoubleLinkedList
        //
        for (long i = 0; i< 10; i++) {
          j = new Long(i * 3);
          d.insert(j);
        }

        // see what is on the DoubleLinkedList
        //
        d.debug(L"after insertion");

        // get the elements and print them
        //
        d.gotoFirst();
        Long* l = d.getFirst();
        l->debug(L"item from the List");
        delete l;

        while((l=d.getNext())!=NULL) {
          d.gotoNext();
          l->debug(L"item from the List");
          delete l;
        }

        // exit gracefully
        //
        Integral::exit();
      }

- This example shows how to check if DoubleLinkedLists are equal.

      #include <DoubleLinkedList.h>
      #include <Char.h>

      int main() {

        // prepare items for the list
        //
        Char** items = new Char*[10];

        // declare a SYSTEM-allocating DoubleLinkedList and insert items into it
        //
        DoubleLinkedList<Char> char_list;

        for (long i = 0; i < 10; i++) {
          items[i] = new Char((unichar)((long)'a' + i));

          // insert the items to the list
          //
          char_list.insert(items[i]);

        }

        // copy the DoubleLinkedList
        //
        DoubleLinkedList<Char> char_copy_list(char_list);

        // declare a third list that is SYSTEM-allocating, and has the same items
        //
        DoubleLinkedList<Char>* system_char_list = new DoubleLinkedList<Char>();
        system_char_list->assign(char_list);

        // see if these DoubleLinkedLists are equivalent
        //
        if(!char_list.eq(char_copy_list) || !system_char_list->eq(char_list)) {

          // exit with error
          //
          Integral::exit();
        }

        // clean up the memory used
        //
        delete system_char_list;
        delete [] items;

        // exit gracefully
        //
        Integral::exit();
      }

notes:

- There are two memory allocation modes for DoubleLinkedList as indicated by the protected member data, alloc_d. The default allocation mode is SYSTEM. If alloc_d is set to SYSTEM, the list handles allocation and deletion of the objects. When the user puts an object into the list, a copy of the object is made and inserted into the list via local memory allocation. Note that this requires a call to the copy constructor so the user will experience an efficiency decrease. When the object is removed from the list, it is automatically deleted.
- If alloc_d is set to USER, the user is required to handle all memory allocation and deletion. When the user adds an object to the list, the object passed in is stored in the list by pointer reference. When an object is removed, the user is required to accept a pointer to the object.
- Unlike other classes, we have two read and write methods in dstr classes. The interface is still the same as that in other classes. The reason behind this is that we can not use "CLASS_NAME" as default argument in the read and write methods here because the data structures build the class name on the fly.