// Copyright (C) 2002 Neil Stevens <neil@qualityassistant.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// 
// Except as contained in this notice, the name(s) of the author(s) shall not be
// used in advertising or otherwise to promote the sale, use or other dealings
// in this Software without prior written authorization from the author(s).

#ifndef QARRAYSTACK_H
#define QARRAYSTACK_H

#include <cassert>
#include <qmemarray.h>

template<class T> class QMemArrayStack : public QMemArray<T>
{
public:
	// empty, with QMemArray's default size
	QMemArrayStack(void);
	// empty, but with an appropriate size
	QMemArrayStack(int);
	// copy
	QMemArrayStack(QMemArrayStack<T> const &);
	// initialize with a pre-filled array
	QMemArrayStack(QMemArray<T> const &);

	// push will resize if needed
	void push(const T &);
	// pop will *not* shrink
	const T &pop(void);

	// just clear it
	void popAll(void);

	unsigned stackSize(void) const;
private:
	unsigned pos;
	bool empty;
};

template<class T> QMemArrayStack<T>::QMemArrayStack(void)
	: QMemArray<T>()
	, pos(0)
	, empty(true)
{
}

template<class T> QMemArrayStack<T>::QMemArrayStack(int a)
	: QMemArray<T>(a)
	, pos(0)
	, empty(true)
{
}

template<class T> QMemArrayStack<T>::QMemArrayStack(const QMemArrayStack<T> &a)
	: QMemArray<T>(a)
	, pos(a.pos)
	, empty(a.empty)
{
}

template<class T> QMemArrayStack<T>::QMemArrayStack(const QMemArray<T> &a)
	: QMemArray<T>(a)
	, pos(a.size() - 1)
	, empty(false)
{
}

template<class T> void QMemArrayStack<T>::push(const T &a)
{
	if(empty)
		empty = false;
	else
		++pos;

	if(pos == QMemArrayStack<T>::size())
		resize(QMemArrayStack<T>::size() + 1);

	(*this)[pos] = a;
}

template<class T> const T &QMemArrayStack<T>::pop(void)
{
	assert(!empty);

	const T &item = (*this)[pos];

	if(pos == 0)
		empty = true;
	else
		--pos;

	return item;
}

template<class T> void QMemArrayStack<T>::popAll(void)
{
	empty = true;
	pos = 0;
}

template<class T> unsigned QMemArrayStack<T>::stackSize(void) const
{
	if(empty)
		return 0;
	else
		return pos + 1;
}

#endif
