//===========================================================================//
// File:     namelist.hpp                                                    //
// Title:    Declaration of NameList classes.                                //
// Project:  Munga                                                           //
// Author:   Ken Olsen (based on work by J.M. Albertson)                     //
// Purpose:  Maintains an unsorted list of strings with (void *) to          //
//           anything the client needs to associate with the string.         //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/07/94  KEO  Convert from Tool Architecture I.                          //
// 01/07/95  KEO  Add ObjectNameList class.                                  //
// 01/25/95  KEO  Move BuildSubList from NameList to ObjectNameList.         //
// 02/12/95  KEO  Add isempty method.                                        //
// 02/17/95  KEO  Add more get methods for entries.                          //
// 03/11/95  KEO  Add IsName and yet more get methods for entries.           //
//---------------------------------------------------------------------------//
// Copyright (c) 1994-1995 Virtual World Entertainment, Inc.                 //
//   All rights reserved worldwide.                                          //
// This unpublished source code is PROPRIETARY and CONFIDENTIAL.             //
//===========================================================================//

#if !defined(NAMELIST_HPP)
	#define NAMELIST_HPP

	#if !defined(STYLE_HPP)
		#include <style.hpp>
	#endif

	class ObjectNameList;
	class ObjectNameList__Entry;
	class NameList;
	class AlphaNameList;

	//=======================================================================
	// Notice:
	//		In using ObjectNameList class, think of AddEntry sort of like a New
	// in the sense that you MUST store the (char *) it returns in the name
	// field of the class you are bonding ObjectNameList to so that when you
	// DeleteEntry you can pass that exact same pointer back.  DeleteEntry
	// does not do a find on the name you pass it.  It expects to receive the
	// pointer that AddEntry gave to you.
	//    This restriction does not exist for NameList and AlphaNameList.
	//-----------------------------------------------------------------------
	// Another Notice:
	//		NameList::Entry objects are never _constructed_ and therefore
	// Check_Pointer(this) is used instead of Check(this).  Also Register_
	// Pointer and Unregister_Pointer are used instead of Register_Object
	// and Unregister_Object.
	//=======================================================================

	//##########################################################################
	//##############    ObjectNameList    ######################################
	//##########################################################################

	class ObjectNameList SIGNATURED
	{
	public:
		typedef ObjectNameList__Entry    Entry;

	protected:
		Entry
			*firstEntry,
			*lastEntry;

	public:
		ObjectNameList();
		virtual
			~ObjectNameList();

		virtual const char*
			AddEntry(
				const char *name,
				void *data
			);
		void*
			FindObject(const char *name);
		void
			DeleteEntry(const char *name);	// ** DANGEROUS!! see notice above **
		int
			EntryCount() const;	// (implementation assumes infrequent use)
		Logical
			IsEmpty() const
				{ Check(this); return firstEntry == NULL && lastEntry == NULL; }
		Entry*
			GetFirstEntry()
				{ Check(this); return firstEntry; }
		const Entry*
			GetFirstEntry() const
				{ Check(this); return firstEntry; }
		Entry*
			GetLastEntry()
				{ Check(this); return lastEntry; }
		const Entry*
			GetLastEntry() const
				{ Check(this); return lastEntry; }
		int
			BuildSubList(
				const ObjectNameList &source_list,
				const char *prefix
			);

		Logical
			TestInstance() const;
		static Logical
			TestClass();
	};

	//##########################################################################
	//##############    ObjectNameList::Entry    ###############################
	//##########################################################################

	class ObjectNameList__Entry
	{
		friend class ObjectNameList;
		friend class NameList;
		friend class AlphaNameList;

	private:
		ObjectNameList::Entry
			*nextEntry;

	public:
		void
			*dataReference;

	protected:
		void
			SetName(const char *name);
	
	public:
		#if defined(USE_SIGNATURE)
			friend int
				Is_Signature_Bad(const volatile ObjectNameList__Entry *);
		#endif

		const char*
			GetName() const
				{
					Check(this);
					return &((const char *)this)[sizeof(ObjectNameList::Entry)];
				}
		Logical
			IsName(const char *name) const;
		void*
			GetObject()
				{ Check(this); return dataReference; }
		void*
			GetData()
				{ Check(this); return dataReference; }
		const void*
			GetData() const
				{ Check(this); return dataReference; }
		char*
			GetChar()
				{ Check(this); return (char *)dataReference; }
		const char*
			GetChar() const
				{ Check(this); return (const char *)dataReference; }
		int
			GetAtoi() const
				{ Check(this); Check_Pointer(dataReference);
					return atoi((const char *)dataReference); }
		long
			GetAtol() const
				{ Check(this); Check_Pointer(dataReference);
					return atol((const char *)dataReference); }
		double
			GetAtof() const
				{ Check(this); Check_Pointer(dataReference);
					return atof((const char *)dataReference); }
		ObjectNameList::Entry*
			GetNextEntry()
				{ Check(this); return nextEntry; }
		const ObjectNameList::Entry*
			GetNextEntry() const
				{ Check(this); return nextEntry; }
		Logical
			TestInstance() const;
	};

	//##########################################################################
	//##############    NameList    ############################################
	//##########################################################################

	class NameList:
		public ObjectNameList
	{
	public:
		NameList();
		~NameList();

		void*
			FindData(const char *name)
				{ return FindObject(name); }
		const char*
			FindName(void *data);
		Entry*
			FindEntry(const char *name);
		Entry*
			FindEntry(void *data);
		void
			DeleteEntry(const char *name);	// this one is searches for name
		static Logical
			TestClass();
	};

	//##########################################################################
	//##############    AlphaNameList    #######################################
	//##########################################################################

	class AlphaNameList:
		public NameList
	{
	public:
		AlphaNameList();
		~AlphaNameList();

		const char*
			AddEntry(
				const char *name,
				void *data
			);
		static Logical
			TestClass();
	};

	//##########################################################################
	//##########################################################################
#endif
