//
// $Id: Stack.h,v 1.14 2005/07/12 19:15:37 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#if !defined(STACK_OL_GUARD)
#define STACK_OL_GUARD

#import <ObjectiveLib/Deque.h>

/**
 * @class OLStack Stack.h ObjectiveLib/Stack.h
 *
 * A first-in-last-out collection. Elements are added to and removed from the
 * top of a stack. Access is provided to the #top element of the stack, which is
 * also the most recently added item. The stack class just provides a restricted
 * view of the underlying container OLDeque for occasions when only the simple
 * functionality of a FILO collection is required. It is not a true
 * @ref Containers "container" because it does not provide
 * @ref Iterators "iterators", so it cannot be used with generic
 * @ref Algorithms "algorithms".
 *
 * @sa OLDeque, OLQueue
 *
 * @ingroup Containers
 */
@interface OLStack : NSObject <OLCopying, NSCoding>
{
@protected
    /**
     * The container that provides the underlying data structure
     */
    OLDeque*    deque;
}

/**
 * Create and return a new stack. The default memory allocator is used to allocate
 * the stack. If the platform and allocator both support autorelease, then the
 * stack will be autoreleased before being returned.
 *
 * @return a new stack
 */
+ (id) stack;

/**
 * Create and return a new stack. The default memory allocator is used to allocate
 * the stack. If the platform and allocator both support autorelease, then the
 * stack will be autoreleased before being returned. The stack is initialized with
 * the contents of @a right.
 *
 * @param right the stack to copy into the new one
 * @return a new stack
 */
+ (id) stackWithStack: (OLStack*)right;

/**
 * @name Initializers and Deallocators
 */
/* @{ */
/**
 * Initialize the stack. The stack is initially empty and uses the default memory
 * allocator.
 *
 * @return a reference to this stack
 */
- (id) init;

/**
 * Initialize the stack. The stack is initially empty and uses the memory
 * allocator @a alloc.
 *
 * @param alloc the memory allocator that should be used
 * @return a reference to this stack
 */
- (id) initWithAllocator: (OLAllocator*)alloc;

/**
 * Initialize the stack. This initializer creates a new stack
 * from an archive and returns it.
 *
 * @post The stack returned will be identical to the stack
 * saved to the archive using the #encodeWithCoder: message.
 *
 * @param decoder the coder which will decode the archived stack
 * @return a reference to this stack
 */
- (id) initWithCoder: (NSCoder*)decoder;

/**
 * Initialize the stack. The memory allocator and all objects are copied from
 * @a stack into this stack.
 *
 * @param stack the stack that should be copied
 * @return a reference to this stack
 */
- (id) initWithStack: (OLStack*)stack;

/**
 * Finalize the stack and deallocate any allocated memory.
 */
- (void) dealloc;
/* @} */

- (id) copyWithAllocator: (OLAllocator*)alloc;
- (id) copyWithZone: (NSZone*)zone;

/**
 * Test whether the stack is empty.
 *
 * @return YES if the stack is empty, NO otherwise
 */
- (BOOL) empty;

/**
 * Encode the stack. The stack is saved to an archive using @a encoder. The stack
 * will be retrieved from the archive using the initializer #initWithCoder:.
 *
 * @param encoder the coder which will save the bit stack to the archive
 */
- (void) encodeWithCoder: (NSCoder*)encoder;

/**
 * Return the memory allocator being used.
 *
 * @return the memory allocator that this stack uses
 */
- (OLAllocator*) allocator;

/**
 * Return whether this stack is equal to another one. Two stacks are considered equal
 * if they both contain the same number of objects that all return YES to the message
 * @c isEqual: and they are in the same order. They do not have to have the same memory
 * allocator in order to be considered equal.
 *
 * @param object the object to test
 * @return YES if @a object is equal to this stack
 */
- (BOOL) isEqual: (id)object;

/**
 * Remove the item at the top of the stack. The element returned by the message
 * #top is removed from the stack.
 *
 * @pre The stack cannot be empty.
 */
- (void) pop;

/**
 * Add an item to the top of the stack. The element @a object will be added to the
 * top of the stack and can be accessed with the message #top.
 *
 * @param object the element to add
 */
- (void) push: (id)object;

/**
 * Return the number of elements in the stack.
 *
 * @return the number of elements
 */
- (unsigned) size;

/**
 * Return the element at the top of the stack. The element returned is the one
 * removed by the message #pop and is also the most recently added element.
 *
 * @return the top element
 */
- (id) top;

@end

#endif
