/*
 * lstack.cpp
 *
 *  Created on: 24.10.2013
 *      Author: trifon
 */

#include "stack.h"
//#define NULL 0
#include <cstddef>

template <typename T>
class LStack : Stack<T> {
private:
	struct elem {
		elem(T const& _inf, elem* _link = NULL) :
			inf(_inf), link(_link) {}
		T inf;
		elem* link;
	};

	elem* stack;

	void copyStack(LStack const& s) {
		// stack is empty
		if (s.empty())
			return;
		// s.stack != NULL
		stack = new elem(s.stack->inf);
		elem *lastCopied = stack, *toCopy = s.stack->link;
		while (toCopy != NULL) {
			lastCopied->link = new elem(toCopy->inf);
			lastCopied = lastCopied->link;
			toCopy = toCopy->link;
		}
	}

	void delStack() {
		/*
		 * T x;
		 * while (pop(x));
		 */
		/*
		elem* prev;
		while (prev = stack) {
			stack = stack->link;
			delete prev;
		}*/
		elem* prev = stack;
		while (stack != NULL) {
			stack = stack->link;
			delete prev;
			prev = stack;
		}
	}


public:
	LStack() : stack(NULL) {}

	LStack(LStack const& s) : stack(NULL) {
		copyStack(s);
	}

	LStack& operator=(LStack const& s) {
		if (&s != this) {
			delStack();
			copyStack(s);
		}
		return *this;
	}

	~LStack() {
		delStack();
	}

	// проверява дали стек е празен
	bool empty() const {
		return stack == NULL;
	}


	// включване на елемент
	bool push(T const& x) {
		elem* p = new elem(x, stack);
		if (p == NULL)
			return false;
		stack = p;
		return true;
	}

	// изключване на елемент
	bool pop(T & x) {
		if (empty())
			return false;
		// stack != NULL
		elem* p = stack;
		x = stack->inf;
		stack = stack->link;
		delete p;
		return true;
	}

	// връх на стека
	bool top(T& x) const {
		if (empty())
			return false;
		x = stack->inf;
		return true;
	}

};