/*FSTACK______________________________________________________________________
function object stack class
by Martin Robinson
______________________________________________________________________________
PREPROCESSOR________________________________________________________________*/

#pragma once
#ifndef _FSTACK
#define _FSTACK

/*CLASS_______________________________________________________________________
____________________________________________________________________________*/

template <typename T>
class fstack{
    fstack * _pop;
    T _data;
public:
    fstack(fstack * stack, T data);
    fstack(T data);
    fstack();
    ~fstack();
    T peek(const int);
    T peek();
    fstack<T> * pop();
    fstack<T> * push(T data);
    int size();
};

//template <typename T>
//typedef fstack<> fstack;

/*META_METHOD_________________________________________________________________
____________________________________________________________________________*/

//constructor
template <typename T>
fstack<T>::fstack(fstack * stack, T data)
{
    _pop = stack;
    _data = data;
}

//constructor
template <typename T>
fstack<T>::fstack(T data)
{
    _pop = 0;
    _data = data;
}

//constructor
template <typename T>
fstack<T>::fstack()
{
    _pop = 0;
    _data = 0;
}

//destructor
template <typename T>
fstack<T>::~fstack()
{
    if (_pop)
        delete _pop;
}

//peek
template <typename T>
T fstack<T>::peek(const int index)
{
    if (index)
        if (index < size())
            return _pop->peek(index-1);
        else
            return 0;
    return _data;
}

//peek
template <typename T>
T fstack<T>::peek()
{
    return _data;
}

//pop
template <typename T>
fstack<T> * fstack<T>::pop()
{
    return _pop;
}

//push
template <typename T>
fstack<T> * fstack<T>::push(T data)
{
    return new fstack<T>(this,data);
}

//size
template <typename T>
int fstack<T>::size()
{
    if (_pop)
        return _pop->size() + 1;
    return 1;
}

#endif
