//
// $Id: Stack.h,v 1.21 2007/03/06 20:42:20 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004-2007
 * 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

#include <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 :
#if defined(OL_NO_OPENSTEP)
    Object <OLStreamable>
#else
    NSObject <OLStreamable, NSCopying, NSCoding>
#endif
{
@protected
    /**
     * The container that provides the underlying data structure
     */
    OLDeque*    deque;
}

/**
 * Create and return a new stack.
 *
 * @note If OpenStep is present the returned object will be autoreleased
 * before being returned.
 *
 * @return a new stack
 */
+ (id) stack;

/**
 * Create and return a new stack. The stack is initialized with
 * the contents of @a right.
 *
 * @note If OpenStep is present the returned object will be autoreleased
 * before being returned.
 *
 * @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.
 *
 * @return a reference to this stack
 */
- (id) init;

#if !defined(OL_NO_OPENSTEP)
/**
 * 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;
#endif

- (id) initWithObjectInStream: (OLObjectInStream*)stream;

/**
 * Initialize the stack. 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.
 */
#if defined(OL_NO_OPENSTEP)
- (id) free;
#else
- (void) dealloc;
#endif
/* @} */

/**
 * Compare this stack to another object. If the other object is of type OLStack, each
 * of the contained objects is compared to the corresponding object in @a other by
 * calling the @c compare: method.
 *
 * @param other the object with which to compare this one
 * @return a value greater than, equal to, or less than zero accoringly as this object
 * is greater than, equal to, or less than @a other
 */
- (int) compare: (id)other;
#if defined(OL_NO_OPENSTEP)
/**
 * Make a copy of this stack.
 *
 * @return the copy
 */
- (id) copy;
#else
/**
 * Make a copy of this stack allocating memory from the given zone.
 *
 * @param zone the zone from which to allocate memory
 * @return the copy
 */
- (id) copyWithZone: (NSZone*)zone;
#endif

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

#if !defined(OL_NO_OPENSTEP)
/**
 * 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;
#endif

/**
 * 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.
 *
 * @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;

- (void) writeSelfToStream: (OLObjectOutStream*)stream;

@end

#endif
