//
// Handles linked lists of VOID pointers.
//

typedef struct tag_item {
	void* m_pdata;	// Pointer to the real data.
	void* m_pnext;
} t_item;

typedef struct tag_list {

	t_item m_items;
	t_item *m_pitemLast;
	int l_iCount;

	tag_list::tag_list()
	{
		Init();
	}

	tag_list::~tag_list()
	{
		DeleteAll();
	}

	void tag_list::Init(void)
	{
		l_iCount = 0;

		::ZeroMemory(&m_items, sizeof(t_item));
		m_pitemLast = &m_items;
	}

	inline int tag_list::GetCount(void)
	{
		return l_iCount;
	}

	inline void DeleteAll(void)
	{
		t_item *l_pitem, *l_pitemNext;

		l_pitemNext = (t_item*)m_items.m_pnext;

		while(l_pitemNext) {

			l_pitem = l_pitemNext;
			l_pitemNext = (t_item*)l_pitem->m_pnext;
			delete l_pitem;
		}

		Init();
	}

	inline void* Add(void* _pdata)
	{
		l_iCount++;

		m_pitemLast->m_pnext = new t_item;
		::ZeroMemory(m_pitemLast->m_pnext, sizeof(t_item));

		m_pitemLast = (t_item*)m_pitemLast->m_pnext;
		m_pitemLast->m_pnext = NULL;

		m_pitemLast->m_pdata = _pdata;
		return _pdata;
	}

	inline BOOL IsEnd(void)
	{
		return (m_items.m_pnext == NULL);
	}

	inline void* GetEndItem(void)
	{
		t_item *l_pitem, *l_pitemNext;

		l_pitemNext = (t_item*)m_items.m_pnext;

		while(l_pitemNext) {

			l_pitem = l_pitemNext;
			l_pitemNext = (t_item*)l_pitem->m_pnext;
		}

		return l_pitem->m_pdata;
	}

	inline t_item* DeleteItem(void* _pdata)
	{
		t_item *l_pitem, *l_pitemNext, *l_pitemPrev;

		l_pitemPrev = (t_item*)&m_items;
		l_pitemNext = (t_item*)m_items.m_pnext;

		while(l_pitemNext) {

			l_pitem = l_pitemNext;

			if(l_pitem->m_pdata == _pdata) {

				l_pitemPrev->m_pnext = l_pitem->m_pnext;

				delete l_pitem;

				if(l_pitem == m_pitemLast) {
					m_pitemLast = l_pitemPrev;
				}
				if(m_pitemLast == &m_items) {
					Init();
				}

				return l_pitemPrev;
			}

			l_pitemPrev = l_pitem;
			l_pitemNext = (t_item*)l_pitem->m_pnext;
		}

		return NULL;
	}

} t_list;

typedef struct tag_listIT {

	t_item* m_pitem;
	t_list* m_plist;	// List we are iterating through.

	tag_listIT::tag_listIT()
	{
		m_pitem = NULL;
	}

	tag_listIT::tag_listIT(t_list* _plist)
	{
		Init(_plist);
	}

	// Moves to the top of the specified list.
	//
	inline void Init(t_list* _plist)
	{
		m_plist = _plist;
		m_pitem = (t_item*)_plist->m_items.m_pnext;
	}

	inline void Init(void)
	{
		m_pitem = (t_item*)m_plist->m_items.m_pnext;
	}

	inline void Delete(void* _pData)
	{
		t_item* l_pitem = (t_item*)m_plist->DeleteItem(_pData);

		if(l_pitem) {

			m_pitem = (t_item*)l_pitem->m_pnext;
		}
		else {

			m_pitem = NULL;
		}
	}

	// Move to the next item in the list.
	//
	inline void Next(void)
	{
		if(m_pitem) {
			m_pitem = (t_item*)m_pitem->m_pnext;
		}
	}

	inline BOOL IsEnd(void)
	{
		return (m_pitem == NULL);
	}

	inline void* GetDataPtr(void)
	{
		return m_pitem->m_pdata;
	}

} t_listIT;
