name: Stack<class TObject>: public DstrBase <TObject>
synopsis:

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

>     #include <Stack.h>
>     Stack();
>     boolean assign(const Stack<TObject>& copy_stack);
>     boolean push(TObject* item);
>     TObject* pop(TObject* item = (TObject*)NULL);
>     const TObject* peek() const;
>     boolean pop(Stack<TObject>& item_stack, long num_items);
>     boolean clear();

quick start:

>     // declare a character stack and push two characters into it
>     //
>     Stack<Char> stack;
>     Char item0(L'a');
>     Char item1(L'b');
>     stack.push(&item0);
>     stack.push(&item1);

>     // pop the top item from the stack
>     //
>     Char* item2 = new Char();
>     stack.pop(item2);

>     if(!item2->eq(item1)) {
>       // error
>     }

description:
The Stack class is a container class that implements a standard stack (last-in, first-out) using a double linked list. For a good reference on stacks, see:

T. Cormen, C. Leiserson, R. Rivest, Introduction to Algorithms, MIT Press, Boston, Massachusetts, USA, pp. 200-203, 1998.

This class uses the double linked list in USER mode, since this list is used to store either the actual data or a pointer to it.
dependencies:

- DstrBase
- DoubleLinkedList
- String
- Char
- Console

public constants:

- define the class name:

      static const String CLASS_NAME = L"Stack";

- i/o related constants:

      static const String DEF_PARAM = L"values";

- default values and arguments:

      static const long POP_ALL = -1;

      static const long POP_TO_MARK = -2;

error codes:

- general Stack class error:

      static const long ERR = 40500;

- error code indicating the stack is empty:

      static const long ERR_EMPTY = 40501

protected data:

- the internal structure of the stack is a DoubleLinkedList:

      DoubleLinkedList<TObject> stack_d;

- the allocation mode:

      ALLOCATION alloc_d;

- 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 StackDiagnose.h in order to avoid the issues related 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):

      ~Stack();

      Stack(ALLOCATION alloc = DEF_ALLOCATION);

      Stack(const Stack<TObject>& copy_stack);

- assign methods:

      boolean assign(const Stack<TObject>& copy_stack);

- operator= methods:

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

- equality methods:

      boolean eq(const Stack<TObject>& compare_stack) const;

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

      long sofSize() const;

      boolean read(Sof& sof_a, long tag_a);

      boolean write(Sof& sof_a, long tag_a) const;

      boolean read(Sof& sof_a, long tag_a, const String& name_a);

      boolean write(Sof& sof_a, long tag_a, const String& name_a) const;

      boolean readData(Sof& sof, const String& pname = DEF_PARAM, long size = SofParser::FULL_OBJECT, boolean param = true, boolean nested = 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:

- extensions to required methods:

      boolean ne(const Stack<TObject>& compare_stack) const;

- stack push methods:

      boolean push(TObject* item);

      boolean push(Stack<TObject>& item_stack);

      boolean push(TObject** items, long num_items);

- other stack manipulation methods:

      const TObject* peek() const;

      TObject* peek();

      TObject* pop(TObject* item = (TObject*)NULL);

      long pop(Stack& items, long num_items);

      boolean popAll(Stack<TObject>& item_stack);

      boolean popToMark(Stack<TObject>& item_stack);

- stack marker positioning methods:

      boolean setMark();

      boolean clearMark();

      boolean markIsSet() const;

      const TObject* getMark() const;

      TObject* getMark();

      boolean isMarkedElement() const;

- stack property methods:

      boolean isEmpty() const;

      long length() const;

      boolean find(TObject* value);

      boolean contains(TObject* value) const;

- stack computation methods:

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

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

- sort and reverse methods:

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

      boolean reverse();

      ALLOCATION getAllocationMode() const;

      boolean setAllocationMode(ALLOCATION alloc);

private methods:

- none.

examples:

- This example shows the basic operation of a stack.

      #include <Char.h>
      #include <Stack.h>

      int main () {

        // local variables
        //
        Stack<Long> s;
        Long j;

        // add 10 items to the stack
        //
        for (long i = 0; i < 10; i++) {
          j = i * 3;
          s.push(&j);
        }

        // see what is on the stack
        //
        s.debug(L"after push");

        // pull things off the stack and print them in order
        //
        while (s.pop(&j) != (Long*)NULL) {
          j.debug(L"pulled off stack");
        }

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

- This example shows the basic operation of a stack in reference mode. Note that memory is manually allocated before pushing it to the stack and deleted upon popping.

      #include <Char.h>
      #include <Stack.h>

      int main () {

        // local variables (note that the stack is set to reference mode)
        //
        Stack<Long> s(USER);
        Long* j;

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

        // see what is on the stack
        //
        s.debug(L"after add");

        // pull things off the stack and print them in order
        //
        while ((j = s.pop()) != (Long*)NULL) {
          j->debug(L"pulled off stack");
          delete j;
        }

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

- This example shows how to check if Stacks are equal:

      #include <Char.h>
      #include <Stack.h>

      int main () {

        // prepare items for the stack
        //
        Char** items = new Char*[5];
        for (long i = 0; i < 5; i++) {
           items[i] = new Char((unichar)((long)(L'a') + i));
        }

        // declare a stack and push items into it
        //
        Stack<Char> char_stack;
        char_stack.push(items, 5);

        // copy the stack
        //
        Stack<Char> copy_char_stack(char_stack);

        // see if these Stacks are equivalent
        //
        if(!char_stack.eq(copy_char_stack)) {

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

        }

        // clean up the memory used
        //
        for (long i = 0; i < 5; i++) {
          delete items[i];
        }
        delete [] items;

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

notes:

- There are two allocation modes for Stack. Only the internal DoubleLinkedList is always in USER mode. this linked list will never be SYSTEM-allocating as the user would not be able to use the pop'd elements if the list was SYSTEM-allocating.
- 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.