Blob Blame Raw
#pragma once

#ifndef TCG_CONTAINERS_READER_H
#define TCG_CONTAINERS_READER_H

// STD includes
#include <stack>

namespace tcg
{

//******************************************************************************
//    Generic Reader declaration
//******************************************************************************

template <typename Val>
class generic_containers_reader
{
public:
	typedef Val value_type;

public:
	virtual void openContainer() = 0;
	virtual void addElement(const value_type &value) = 0;
	virtual void closeContainer() = 0;

	// NOTE: Algorithms may require the openContainer() function to accept the
	// container's header data. Check the algorithms description if necessary.
};

//******************************************************************************
//    Some Actual Container Readers
//******************************************************************************

template <typename Container, typename Val = typename Container::value_type>
class sequential_reader
{
	Container *m_values;

public:
	typedef Container container_type;
	typedef Val value_type;

public:
	sequential_reader(Container *container)
		: m_values(container) {}

	void openContainer() { m_values->clear(); }
	void addElement(const value_type &val) { m_values->push_back(val); }
	void closeContainer() {}

	const container_type *values() const { return m_values; }
	container_type *values() { return m_values; }
};

//------------------------------------------------------------------

template <typename Container, typename Val = typename Container::value_type>
class ordered_reader
{
	Container *m_values;

public:
	typedef Container container_type;
	typedef Val value_type;

public:
	ordered_reader(Container &container)
		: m_values(container) {}

	void openContainer() { m_values->clear(); }
	void addElement(const value_type &val) { m_values->insert(val); }
	void closeContainer() {}

	const container_type *values() const { return m_values; }
	container_type *values() { return m_values; }
};

//------------------------------------------------------------------

template <typename Container, typename ReaderType, typename Val = typename ReaderType::value_type>
class multiple_reader
{
public:
	typedef Container container_type;
	typedef ReaderType reader_type;
	typedef Val value_type;

protected:
	Container *m_storage;
	std::stack<reader_type> m_stack;

public:
	multiple_reader(Container *storage)
		: m_storage(storage) {}

	reader_type &reader() { return m_stack.top(); }

	void openContainer() { m_stack.push(reader_type(new typename reader_type::container_type)); }
	void addElement(const value_type &val) { reader().addElement(val); }
	void closeContainer()
	{
		if (reader().values()->empty())
			delete reader().values();
		else
			m_storage->push_back(reader().values());

		m_stack.pop();
	}

	const container_type &storage() const { return m_storage; }
	container_type &storage() { return m_storage; }
};

} //namespace tcg

#endif //TCG_CONTAINERS_READER_H