-----=====notthecheatr stack object=====-----

=====Introduction=====
What is a stack?  A stack is a simple linear data structure, one which may be used for example to store a list.
The name stack is actually very descriptive;  imagine a stack of plates.  You can put a plate on top, and you
can take one off the top, but you can't take a plate from anywhere else or put one anywhere else.  In computer
science, it's the same thing except with variables instead of plates.  A stack is a LIFO (Last-In First-Out)
buffer, meaning the last item you put on the stack will be the first one you take off.  Normally stacks are
manipulated using two functions:  Push and Pop.  These put an item on the stack and take one off, respectively.
My stack also supports two other operations, read and write, which let you access the top item without removing
it or adding a new one.  There are also several functions which let you swap the top item and the one directly
below it.  And of course you can always find out exactly how many items are on the stack.

Stacks are useful for a great deal of things;  the most common usage (but more obscure) is the fact that the
assembly generated by your compiler makes liberal use of a stack.  For example, when you call a function or sub
and you pass arguments to it, those arguments are put on the stack and the function/sub reads them off the stack.
Also stored on the stack is the address which the processor is to return to when the function/sub finishes
executing.

Other usages include evaluating expressions in reverse polish notation (RPN), where two numbers are pushed on the
stack and an operator is applied using those two numbers, and scripting (for example, my BrainF*** interpreter
uses a stack to keep track of where to return to when ] is encountered).

Because my stack object is an object, it takes care of all the dirty work, making sure it takes up as much space in
memory as it needs to (and no more or less than that), initializing itself into a valid stack object when it is
first created and deallocating all the memory once it is destroyed.  It's designed to be thread safe, locking an
internal mutex during all write operations (all internals are hidden, so the only way to access any data on the
stack is through the interface which automatically locks the mutex).  And it should be about as fast as it could
possibly be, though I don't claim to be a perfect programmer by any means.

There is a special option of preallocating space for the stack, meaning that you can set a minimum amount
of space to maintain even if it's not using all that space - for example, you can instruct it to maintain enough
space to store 5 items even if there are less than 5 items on the stack.  This can be used to speed things up
since it won't be reallocating memory each time you add an item to the stack or remove one, but of course if the
number of items on the stack exceed this amount it will revert to reallocating each time.  Keeping the
preallocation value high will make things faster, since reallocating will occur a lot less (reallocating can slow
you down a lot, since in some cases all the items in the stack would need to be moved to another location in
memory) but it will also use more memory, so you'll want to come to a good balance between speed and memory
usage.

=====Usage=====
To use, you must first include the stack .BAS file in your program:
  #Include Once "stack.bas"
The only reason it's not a proper module (stack.bi and libstack.a) is that we want to be able to
specify what type of data is stored on the stack.  The first non-comment lines of the stack objects
.BAS file look like this:
  #define STACK_DATA_TYPE uInteger
  #define DEFAULT_STACK_DATA 0
This means the stack stores uIntegers and if you request a stack item when the stack is empty it will return 0.
You can set this to any other type except Strings and it should work just fine.  Most likely if you use this
a lot you'll set it to Any Ptr (which is the same size as uInteger) - you can point it at any data type, including
objects, if you do that.

Once that's taken care of, you simply need to Dim a stack object in your program:
  Dim As stack myStack
Or you can create a stack with a pointer:
  Dim As stack Ptr myStack = New(stack)
(just remember to use -> instead of . to access methods if it's a pointer)

It will automatically initialize itself and do everything it needs to be a valid stack object.  It starts
out empty;  you push items onto it or pop them off as you need to:
  myStack.push(1)
  myStack.push(2)
  myStack.push(3)
  Print Str(myStack.pop())
  Print Str(myStack.pop())
  Print Str(myStack.pop())
Notice the items are popped off in reverse order;  this is true of all stacks.

You can also read or write the top item without actually removing it or adding a new one.  However, you can only
do this if there *is* a top item on the stack, that is, if the stack is not empty:
  myStack.push(1)
  Print Str(myStack.read())
  myStack.write(2)
  Print Str(myStack.read())
Use push to put a new item on the stack and pop to take one off;  use read to read the top item without removing it
and write to change the top item without adding a new one.

If you want to swap the top and second item on the stack, you may, using
  myStack.swapTop()
You may also swap conditionally;  for example, if you want to make sure that the top item is the greater of the
two values, you would use
  myStack.swapIfGreater()
which only swaps if the second item is greater than the first.  There is also a swapIfLess(), which swaps if the
second item is less than the first.

You can also remove all the items from the stack at once:
  myStack.popAll()

When you first create an object, you may specify how much to preallocate.  For example, if you want to allocate
enough space for three items:
  Dim As stack myStack = stack(3)
You don't have to do this;  the default if you don't is just enough space for one item.  At any time afterwards
you may change this - for example, to change it to 5:
  myStack.preAllocate = 5
you may of course check what the current value of preallocate is as well:
  Print Str(myStack.preAllocate)
As explained earlier, this is a hint for the stack object.  Setting preallocate is like setting a minimum amount
of space the stack should use.  This way, so long as you are below the minimum, adding or removing items on
the stack will not cause the stack to change size, so it's much faster.  Once you exceed the minimum, you may
experience a slowdown (particularly if you add a lot of items) until you're below the minimum again.  It might
be wise to check how many items are on the stack before entering a section in which you will be doing a lot of
push/pop operations;  if you're above the preallocation value, you should set it higher to avoid slowing down.
As stated earlier, you should be careful to achieve a good balance between speed and low memory usage, as setting
it high uses lots of memory while setting it low can make things very slow.

Finally, you can find out how many items are in a stack with the property numItems:
  Print Str(myStack.numItems)

These are all the basic things you can do with a stack.  Once you're done with the stack, if it's a pointer created
with New use Delete.  Otherwise, just popAll (so you aren't using that extra memory) and leave it until the end
of the program when it will be destroyed.  Either way, when the object is destroyed it will clean up all the memory it takes up by removing
all the items it contains.  For obvious reasons, you should not attempt to use a linkedList object after it
has been destroyed;  in fact, all methods check to ensure the object is still valid and, if not, will not do
anything.

=====Example=====
An example is provided, in test.bas.  It assumes the stack items are uInteger, and it demonstrates all the major
operations you would perform on a stack.  Read through it, perhaps run it, to see how it all works.