//:Header:64, "llqueue_strarray", 3b93fb4e
//
// File: llqueue_str_array.h
//
// G A M E.O.N.E - LOW LEVEL LIB V1.0
// Copyright (C) 2001 LEVEL ONE ENTERTAINMENT, 
// Licensed under the terms of LGPL.
//:---------------------------------------------------------------------------
//:Description
//
// Template Array für schnellen Zugriff auf Strings
//
//:-----------------------------------------------------------------------------

#if !defined(LLQUEUE_STR_ARRAY_INCLUDED)
#define LLQUEUE_STR_ARRAY_INCLUDED

//:Include
#include "lib_base.h"
#include <stdlib.h> // für qsort

//:>              +------------------------------------------+
//:>--------------|    llqueue_strarray Class Declaration    |---------------
//:>              +------------------------------------------+
//:Class

int SortLenQueue( const void * left, const void * right );
int SortStringQueue( const void * left, const void * right );



class _string_entry
{
public:
	_string_entry();
	~_string_entry();
	int		m_len;		// Länge von Key
	char *	m_key;		// Key-string
	char *	m_data;		// Data
};

class _len_queue
{
public:
	_len_queue();
	~_len_queue();
	

	_string_entry * FindEntry(const char *key);
	void AddEntry(_string_entry *S);

	int	m_len;									// länge der Schlüssel die diese Queue verwaltet
	queue<_string_entry>	m_entry_queue;		// queue mit StringEntrys deren Key die Länge m_len hat
};


class llqueue_strarray
{
public:
	llqueue_strarray();
	~llqueue_strarray();
	
	int GetCount();
	void AddEntry(const char *str, const char *data);
	_string_entry * FindEntry(const char *key);
	void Clear();
	
private:
	_string_entry * CreateStringEntry(const char *str);
	
	queue<_len_queue>	m_data;
};

//:>                   +-----------------------------------+
//:>-------------------|    Member Function Definitions    |--------------------
//:>                   +-----------------------------------+

inline llqueue_strarray::llqueue_strarray()
{
}
inline llqueue_strarray::~llqueue_strarray()
{
	Clear();
}

inline _string_entry::_string_entry()
{
}
inline _string_entry::~_string_entry()
{
	delete m_data;
	delete m_key;
}
inline _len_queue::_len_queue()
{
}
inline _len_queue::~_len_queue()
{
	while( _string_entry * S = m_entry_queue.Get() )
		delete S;
}

inline int llqueue_strarray::GetCount()
{
	return m_data.InQueue();
}

inline void llqueue_strarray::AddEntry(const char *str,const char * data)
{
	SYS_ASSERT_PTR(str);
	
	if( 0 != FindEntry(str) )	// bereist vorhanden?
		return;					// ja dann raus
	
	_string_entry *N = CreateStringEntry(str);
	if(N==0) return;

	/*
	 *	Datenfeld transportieren
	 */
	N->m_data = new char [ strlen(data) + 1 ];
	strcpy(N->m_data,data);

	/*
	 *	Len queue fiden, bzw neu anlegen
	 */
	m_data.Reset();
	while( _len_queue *L = m_data.Next() )
	{
		if( N->m_len == L->m_len )
		{
			L->AddEntry(N);
			return;
		}
	}
	
	_len_queue * L = new _len_queue;

	L->m_len = N->m_len;
	L->AddEntry(N);
	m_data.Put(L);
	m_data.Sort(SortLenQueue);
}

inline void _len_queue::AddEntry(_string_entry *S)
{
	SYS_ASSERT_PTR(S);
	m_entry_queue.Put(S);
	m_entry_queue.Sort(SortStringQueue);
}


inline _string_entry * _len_queue::FindEntry(const char *str)
{
	m_entry_queue.Reset();
	while( _string_entry * E = m_entry_queue.Next() )
	{
		if( 0 == strcmp(E->m_key, str ) )
		{
			return E;
		}
	}
	return 0;
}

inline _string_entry * llqueue_strarray::FindEntry(const char *str)
{
	SYS_ASSERT_PTR(str);

	int len = strlen( str );
	if( len < 1 )
	{
		return 0;
	}


	m_data.Reset();
	while( _len_queue *L = m_data.Next() )
	{
		if( len == L->m_len )
		{
			return L->FindEntry(str);
		}
	}
		
	return 0;
}

inline _string_entry * llqueue_strarray::CreateStringEntry(const char *str)
{
	SYS_ASSERT_PTR(str);
	
	int len = strlen( str );
	if( len < 1 )
	{
		return 0;
	}
	
	_string_entry * N = new _string_entry;
	N->m_len = len;
	N->m_key = new char [len + 1];

	len = 0;
	while( *str )
	{
		N->m_key[len++] = *str ++;
	}

	N->m_key[len] = 0;

	return N;
}

inline void llqueue_strarray::Clear()
{
	while( _len_queue *L = m_data.Get() )
	{
		delete L;
	}
}

#endif