#ifndef DEBUG_H
#define DEBUG_H
#include <vector>
#include <list>
#include <iterator>
#include <sstream>
using namespace std;

struct show
{
public:
    ostream * out;
    int size;
    show() { size = 3; }
    show(int number) { size = number; }
};

inline show operator<<(ostream & out, const show & s)
{
    show n = s;
    n.out = &out;
    return n;
}

template<class T>
inline ostream & operator<<(show s, const T & t)
{
    *s.out << t;
    return *s.out;
}

template<class T>
inline ostream & operator<<(show s, const vector<T> & t)
{
    *s.out << "{";
    unsigned i = 0;
    for(;
        (i < t.size()) &&
        (i < static_cast<unsigned>(s.size) || s.size == -1 );
    i++)
    {
        *s.out << t[i];
        if(i != t.size() - 1)
            *s.out << ", ";
    }
    if(i < t.size())
    {
        *s.out << "... <" << (t.size() - i - 1) << "> ... ";
        *s.out << ", " << t[t.size() - 1];
    }
    *s.out << "}";
    return *s.out;
}

template<class T>
inline ostream & operator<<(ostream & out, const vector<T> & t)
{
    out << show() << t;
    return out;
}

template<class T>
inline ostream & operator<<(show s, const list<T> & t)
{
    typename list<T>::const_iterator p = t.begin();
    *s.out << "{";
    unsigned i = 0;
    for(;
        (i < t.size()) &&
        (i < static_cast<unsigned>(s.size) || s.size == -1 );
    i++)
    {
        *s.out << (*p);
        if(i != t.size() - 1)
            *s.out << ", ";
        p++;
    }
    if(i < t.size())
    {
        *s.out << "... <" << (t.size() - i - 1) << "> ... ";
        *s.out << ", " << t.back();
    }
    *s.out << "}";
    return *s.out;
}

template<class T>
inline ostream & operator<<(ostream & out, const list<T> & t)
{
    out << show() << t;
    return out;
}

#endif // DEBUG_H

