//===========================================================================//
// File:	vchain.hh                                                           //
// Project: MUNGA           Brick: Connection Library                        //
// Contents: Interface specification of VChain class                         //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/02/94  ECH  Initial coding.                                            //
// 12/12/94  ECH  Changed release handling											  //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//

#if !defined(VCHAIN_HPP)
#	define VCHAIN_HPP

#	if !defined(NODE_HPP)
#		include <node.hpp>
#	endif

#	if !defined(SRTSKT_HPP)
#		include <srtskt.hpp>
#	endif

#	if !defined(MEMBLOCK_HPP)
#		include <memblock.hpp>
#	endif

	class VChain;
	class VChainIterator;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class VChainLink:
		public Link
	{
		friend class VChain;
		friend class VChainIterator;

	public:
		~VChainLink();
		Logical
			TestInstance() const;

	protected:
		VChainLink(
			VChain *vchain,
			Plug *plug
		);

	private:
		void
			SetupVChainLinks(
				VChainLink *next,
				VChainLink *prev
			);

		VChainLink *next;
		VChainLink *prev;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLinkOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   #define VCHAINLINK_MEMORYBLOCK_ALLOCATION (100)

	template <class V> class VChainLinkOf:
		public VChainLink
	{
	public:
		VChainLinkOf(
			VChain *vchain,
			Plug *plug,
			const V &value
		);
		~VChainLinkOf();

		void*
			operator new(size_t);
		void
			operator delete(void *where);

		V
			GetValue()
				{return value;}
		V*
			GetValuePointer()
				{return &value;}

	private:
		static MemoryBlock
			*allocatedMemory;
		static CollectionSize
			allocationCount;

		V value;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLinkOf templates ~~~~~~~~~~~~~~~~~~~~~~~~

	template <class V> MemoryBlock*
		VChainLinkOf<V>::allocatedMemory = NULL;
	template <class V> CollectionSize
		VChainLinkOf<V>::allocationCount = 0;

	template <class V>
		VChainLinkOf<V>::VChainLinkOf(
			VChain *vchain,
			Plug *plug,
			const V &value
		):
			VChainLink(vchain, plug)
	{
		this->value = value;
	}

	template <class V>
		VChainLinkOf<V>::~VChainLinkOf()
	{
	}

	#if 0
   template <class V> void*
      VChainLinkOf<V>::operator new(size_t)
   {
   	if (allocatedMemory == NULL)
      {
      	allocatedMemory =
				new MemoryBlock(
					sizeof(VChainLinkOf<V>),
					VCHAINLINK_MEMORYBLOCK_ALLOCATION,
					VCHAINLINK_MEMORYBLOCK_ALLOCATION
				);
		}
		Check(allocatedMemory);
		return allocatedMemory->New();
	}

	template <class V> void
		VChainLinkOf<V>::operator delete(void *where)
	{
		Check(allocatedMemory);
		allocatedMemory->Delete(where);
	}
	#else
	template <class V> void*
		VChainLinkOf<V>::operator new(size_t)
	{
		Verify(allocationCount >= 0);
		if (allocationCount++ == 0)
		{
			allocatedMemory =
				new MemoryBlock(
					sizeof(VChainLinkOf<V>),
					VCHAINLINK_MEMORYBLOCK_ALLOCATION,
					VCHAINLINK_MEMORYBLOCK_ALLOCATION,
					"VChainLinkOf"
				);
			Register_Object(allocatedMemory);
		}
		Verify(allocationCount < INT_MAX);
		Check(allocatedMemory);
		return allocatedMemory->New();
	}

	template <class V> void
		VChainLinkOf<V>::operator delete(void *where)
	{
		Check(allocatedMemory);
		allocatedMemory->Delete(where);
		if (--allocationCount == 0)
		{
			Unregister_Object(allocatedMemory);
			delete allocatedMemory;
			allocatedMemory = NULL;
		}
		Verify(allocationCount >= 0);
	}
	#endif

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class VChain:
		public SortedSocket
	{
		friend class VChainLink;
		friend class VChainIterator;

	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructor, Destructor and testing
		//--------------------------------------------------------------------
		//
		VChain(
			Node *node,
			Logical has_unique_entries
		);
		~VChain();

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

	protected:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Protected interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		void
			AddImplementation(Plug *);
		void
			AddValueImplementation(
				Plug *plug,
				const void *value
			);
		Plug
			*FindImplementation(const void *value);

	private:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		virtual VChainLink
			*MakeVChainLink(
				Plug *plug,
				const void *value
			);
		virtual int
			CompareVChainLinks(
				VChainLink *link1,
				VChainLink *link2
			);
		virtual int
			CompareValueToVChainLink(
				const void *value,
				VChainLink *link
			);

		VChainLink*
			SearchForValue(const void *value);

		//
		//--------------------------------------------------------------------
		// Private data
		//--------------------------------------------------------------------
		//
		VChainLink *head;
      VChainLink *tail;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   #define VCHAIN_MEMORYBLOCK_ALLOCATION (100)

	template <class T, class V> class VChainOf:
		public VChain
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		VChainOf(
			Node *node,
			Logical has_unique_entries
		);
		~VChainOf();

		void*
			operator new(size_t);
		void
			operator delete(void *where);

		//
		//--------------------------------------------------------------------
		// Socket methods (see Socket for full listing)
		//--------------------------------------------------------------------
		//
		void
			AddValue(
				T plug,
				const V &value
			)
				{AddValueImplementation(Cast_Object(Plug*,plug), &value);}
		T
			Find(const V &value)
				{return (T)FindImplementation(&value);}

	private:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		VChainLink
			*MakeVChainLink(
				Plug *plug,
				const void *value
			)
				{return new VChainLinkOf<V>(this, plug, *(V*)value);}
		int
			CompareVChainLinks(
				VChainLink *link1,
				VChainLink *link2
			);
		int
			CompareValueToVChainLink(
				const void *value,
				VChainLink *link
			);

		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private data
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		static MemoryBlock
			*allocatedMemory;
		static CollectionSize
			allocationCount;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V> MemoryBlock*
		VChainOf<T, V>::allocatedMemory = NULL;
	template <class T, class V> CollectionSize
		VChainOf<T, V>::allocationCount = 0;

	template <class T, class V>
		VChainOf<T, V>::VChainOf(
			Node *node,
			Logical has_unique_entries
		):
			VChain(
				node,
				has_unique_entries
			)
	{
	}

	template <class T, class V>
		VChainOf<T, V>::~VChainOf()
	{
	}

	template <class T, class V> int
		VChainOf<T, V>::CompareVChainLinks(
			VChainLink *node1,
			VChainLink *node2
		)
	{
		V *ptr1 = Cast_Object(VChainLinkOf<V>*, node1)->GetValuePointer();
		V *ptr2 = Cast_Object(VChainLinkOf<V>*, node2)->GetValuePointer();

		Check_Pointer(ptr1);
		Check_Pointer(ptr2);

		if (*ptr1 == *ptr2)
			return 0;
		else
			return ((*ptr1 > *ptr2) ? 1 : -1);
	}

	template <class T, class V> int
		VChainOf<T, V>::CompareValueToVChainLink(
			const void *value,
			VChainLink *node
		)
	{
		Check_Pointer(value);

		V *ptr = Cast_Object(VChainLinkOf<V>*, node)->GetValuePointer();
		Check_Pointer(ptr);

		if (*(V*)value == *ptr)
			return 0;
		else
			return (*(V*)value > *ptr) ? 1 : -1;
	}

	#if 0
	template <class T, class V> void*
		VChainOf<T, V>::operator new(size_t)
	{
		if (allocatedMemory == NULL)
		{
			allocatedMemory =
				new MemoryBlock(
					sizeof(VChainOf<T, V>),
					VCHAIN_MEMORYBLOCK_ALLOCATION,
					VCHAIN_MEMORYBLOCK_ALLOCATION
				);
		}
		Check(allocatedMemory);
		return allocatedMemory->New();
	}

	template <class T, class V> void
		VChainOf<T, V>::operator delete(void *where)
	{
		Check(allocatedMemory);
		allocatedMemory->Delete(where);
	}
	#else
	template <class T, class V> void*
		VChainOf<T, V>::operator new(size_t)
	{
		Verify(allocationCount >= 0);
		if (allocationCount++ == 0)
		{
			allocatedMemory =
				new MemoryBlock(
					sizeof(VChainOf<T, V>),
					VCHAIN_MEMORYBLOCK_ALLOCATION,
					VCHAIN_MEMORYBLOCK_ALLOCATION,
					"VChainOf"
				);
			Register_Object(allocatedMemory);
		}
		Verify(allocationCount < INT_MAX);
		Check(allocatedMemory);
		return allocatedMemory->New();
	}

	template <class T, class V> void
		VChainOf<T, V>::operator delete(void *where)
	{
		Check(allocatedMemory);
		allocatedMemory->Delete(where);
		if (--allocationCount == 0)
		{
			Unregister_Object(allocatedMemory);
			delete allocatedMemory;
			allocatedMemory = NULL;
		}
		Verify(allocationCount >= 0);
	}
	#endif

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~

	class VChainIterator:
		public SortedIterator
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructors, Destructor and testing
		//--------------------------------------------------------------------
		//
		VChainIterator(VChain *vchain);
		VChainIterator(const VChainIterator *iterator);
		~VChainIterator();
		Logical
			TestInstance() const;

		//
		//--------------------------------------------------------------------
		// Iterator methods (see Iterator for full listing)
		//--------------------------------------------------------------------
		//
		void
			First();
		void
			Last();
		void
			Next();
		void
			Previous();
		CollectionSize
			GetSize();
		void
			Remove();

	protected:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Protected interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		void*
			ReadAndNextImplementation();
		void*
			ReadAndPreviousImplementation();
		void*
			GetCurrentImplementation();
		void*
			GetNthImplementation(
				CollectionSize index
			);
		Plug*
			FindImplementation(const void *value);

	protected:
		//
		//--------------------------------------------------------------------
		// Protected data
		//--------------------------------------------------------------------
		//
		VChainLink
			*currentLink;

	private:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Private interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//
		void
			ReceiveMemo(
				IteratorMemo memo,
				void *content
			);
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V> class VChainIteratorOf:
		public VChainIterator
	{
	public:
		//
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		// Public interface
		//--------------------------------------------------------------------
		//--------------------------------------------------------------------
		//

		//
		//--------------------------------------------------------------------
		// Constructors and Destructor
		//--------------------------------------------------------------------
		//
		VChainIteratorOf(VChainOf<T, V> *vchain);
		VChainIteratorOf(VChainOf<T, V> &vchain);
		VChainIteratorOf(const VChainIteratorOf<T, V> &iterator);
		~VChainIteratorOf();

		//
		//--------------------------------------------------------------------
		// Iterator methods (see Iterator for full listing)
		//--------------------------------------------------------------------
		//
		T
			ReadAndNext()
				{return (T)ReadAndNextImplementation();}
		T
			ReadAndPrevious()
				{return (T)ReadAndPreviousImplementation();}
		T
			GetCurrent()
				{return (T)GetCurrentImplementation();}
		T
			GetNth(CollectionSize index)
				{return (T)GetNthImplementation(index);}
		T
			Find(const V &value)
				{return (T)FindImplementation(&value);}
		V
			GetValue()
				{return Cast_Object(VChainLinkOf<V>*, currentLink)->GetValue();}
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~

	template <class T, class V>
		VChainIteratorOf<T, V>::VChainIteratorOf(VChainOf<T, V> *vchain):
			VChainIterator(vchain)
	{
	}

	template <class T, class V>
		VChainIteratorOf<T, V>::VChainIteratorOf(VChainOf<T, V> &vchain):
			VChainIterator(&vchain)
	{
	}

	template <class T, class V>
		VChainIteratorOf<T, V>::VChainIteratorOf(
			const VChainIteratorOf<T, V> &iterator
		):
			VChainIterator(&iterator)
	{
	}

	template <class T, class V>
		VChainIteratorOf<T, V>::~VChainIteratorOf()
	{
	}

#endif
