#ifndef swShader_FIFOCache_hpp
#define swShader_FIFOCache_hpp

namespace swShader
{
	template<class Key, class Data>
	class FIFOCache
	{
	public:
		FIFOCache(int n);

		~FIFOCache();

		Data *query(const Key &key) const;
		Data *add(const Key &key, Data *data);

		void clear();

	private:
		const unsigned int size;
		unsigned int top;

		Key *key;
		Data **data;
	};
}

namespace swShader
{
	template<class Key, class Data>
	FIFOCache<Key, Data>::FIFOCache(int n) : size(n)
	{
		top = 0;

		key = new Key[n];

		data = new Data*[n];
		for(unsigned int i = 0; i < size; i++) data[i] = 0;
	}

	template<class Key, class Data>
	FIFOCache<Key, Data>::~FIFOCache()
	{
		delete[] key;
		key = 0;

		for(unsigned int i = 0; i < size; i++)
		{
			delete data[i];
			data[i] = 0;
		}

		delete[] data;
		data = 0;
	}

	template<class Key, class Data>
	Data *FIFOCache<Key, Data>::query(const Key &key) const
	{
		for(unsigned int i = 0; i < size; i++)
		{
			unsigned int j = (top - i) % size;

			if(key == this->key[j])
			{
				return data[j];
			}
		}

		return 0;   // Not found
	}
	
	template<class Key, class Data>
	Data *FIFOCache<Key, Data>::add(const Key &key, Data *data)
	{
		top++;
		unsigned int i = top % size;

		this->key[i] = key;
	
		delete this->data[i];
		this->data[i] = data;

		return data;
	}

	template<class Key, class Data>
	void FIFOCache<Key, Data>::clear()
	{
		for(unsigned int i = 0; i < size; i++)
		{
			delete data[i];
			data[i] = 0;
		}
	}
}

#endif   // swShader_FIFOCache_hpp
