mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-31 12:41:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			220 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef __RANGE_LIST_H
 | |
| #define __RANGE_LIST_H
 | |
| 
 | |
| #include "DS_OrderedList.h"
 | |
| #include "BitStream.h"
 | |
| #include "RakMemoryOverride.h"
 | |
| #include <assert.h>
 | |
| 
 | |
| namespace DataStructures
 | |
| {
 | |
|     template <class range_type>
 | |
| 	struct RangeNode : public RakNet::RakMemoryOverride
 | |
|     {
 | |
|         RangeNode() {}
 | |
|         ~RangeNode() {}
 | |
|         RangeNode(range_type min, range_type max) {minIndex=min; maxIndex=max;}
 | |
|         range_type minIndex;
 | |
|         range_type maxIndex;
 | |
|     };
 | |
| 
 | |
| 
 | |
|     template <class range_type>
 | |
|     int RangeNodeComp(const range_type &a, const RangeNode<range_type> &b)
 | |
|     {
 | |
|         if (a<b.minIndex)
 | |
|             return -1;
 | |
|         if (a==b.minIndex)
 | |
|             return 0;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	class RAK_DLL_EXPORT RangeList : public RakNet::RakMemoryOverride
 | |
| 	{
 | |
| 	public:
 | |
| 		RangeList();
 | |
| 		~RangeList();
 | |
| 		void Insert(range_type index);
 | |
| 		void Clear(void);
 | |
| 		unsigned Size(void) const;
 | |
| 		unsigned RangeSum(void) const;
 | |
| 		BitSize_t Serialize(RakNet::BitStream *in, BitSize_t maxBits, bool clearSerialized);
 | |
| 		bool Deserialize(RakNet::BitStream *out);
 | |
| 
 | |
| 		DataStructures::OrderedList<range_type, RangeNode<range_type> , RangeNodeComp<range_type> > ranges;
 | |
| 	};
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	BitSize_t RangeList<range_type>::Serialize(RakNet::BitStream *in, BitSize_t maxBits, bool clearSerialized)
 | |
| 	{
 | |
| 		assert(ranges.Size() < (unsigned short)-1);
 | |
| 		RakNet::BitStream tempBS;
 | |
| 		BitSize_t bitsWritten;
 | |
| 		unsigned short countWritten;
 | |
| 		unsigned i;
 | |
| 		countWritten=0;
 | |
| 		bitsWritten=0;
 | |
| 		for (i=0; i < ranges.Size(); i++)
 | |
| 		{
 | |
| 			if ((int)sizeof(unsigned short)*8+bitsWritten+(int)sizeof(range_type)*8*2+1>maxBits)
 | |
| 				break;
 | |
| 			tempBS.Write(ranges[i].minIndex==ranges[i].maxIndex);
 | |
| 			tempBS.Write(ranges[i].minIndex);
 | |
| 			bitsWritten+=sizeof(range_type)*8+1;
 | |
| 			if (ranges[i].minIndex!=ranges[i].maxIndex)
 | |
| 			{
 | |
| 				tempBS.Write(ranges[i].maxIndex);
 | |
| 				bitsWritten+=sizeof(range_type)*8;
 | |
| 			}
 | |
| 			countWritten++;
 | |
| 		}
 | |
| 
 | |
| 		BitSize_t before=in->GetWriteOffset();
 | |
| 		in->WriteCompressed(countWritten);
 | |
| 		bitsWritten+=in->GetWriteOffset()-before;
 | |
| 	//	printf("%i ", in->GetNumberOfBitsUsed());
 | |
| 		in->Write(&tempBS, tempBS.GetNumberOfBitsUsed());
 | |
| 	//	printf("%i %i \n", tempBS.GetNumberOfBitsUsed(),in->GetNumberOfBitsUsed());
 | |
| 
 | |
| 		if (clearSerialized && countWritten)
 | |
| 		{
 | |
| 			unsigned rangeSize=ranges.Size();
 | |
| 			for (i=0; i < rangeSize-countWritten; i++)
 | |
| 			{
 | |
| 				ranges[i]=ranges[i+countWritten];
 | |
| 			}
 | |
| 			ranges.RemoveFromEnd(countWritten);
 | |
| 		}
 | |
| 
 | |
| 		return bitsWritten;
 | |
| 	}
 | |
| 	template <class range_type>
 | |
| 	bool RangeList<range_type>::Deserialize(RakNet::BitStream *out)
 | |
| 	{
 | |
| 		ranges.Clear();
 | |
| 		unsigned short count;
 | |
| 		out->ReadCompressed(count);
 | |
| 		unsigned short i;
 | |
| 		range_type min,max;
 | |
| 		bool maxEqualToMin=false;
 | |
| 
 | |
| 		for (i=0; i < count; i++)
 | |
| 		{
 | |
| 			out->Read(maxEqualToMin);
 | |
| 			if (out->Read(min)==false)
 | |
| 				return false;
 | |
| 			if (maxEqualToMin==false)
 | |
| 			{
 | |
| 				if (out->Read(max)==false)
 | |
| 					return false;
 | |
| 				if (max<min)
 | |
| 					return false;
 | |
| 			}
 | |
| 			else
 | |
| 				max=min;
 | |
| 
 | |
| 			ranges.InsertAtEnd(RangeNode<range_type>(min,max));
 | |
| 		}
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	RangeList<range_type>::RangeList()
 | |
| 	{
 | |
| 		RangeNodeComp<range_type>(0, RangeNode<range_type>());
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	RangeList<range_type>::~RangeList()
 | |
| 	{
 | |
| 		Clear();
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	void RangeList<range_type>::Insert(range_type index)
 | |
| 	{
 | |
| 		if (ranges.Size()==0)
 | |
| 		{
 | |
| 			ranges.Insert(index, RangeNode<range_type>(index, index), true);
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		bool objectExists;
 | |
| 		unsigned insertionIndex=ranges.GetIndexFromKey(index, &objectExists);
 | |
| 		if (insertionIndex==ranges.Size())
 | |
| 		{
 | |
| 			if (index == ranges[insertionIndex-1].maxIndex+1)
 | |
| 				ranges[insertionIndex-1].maxIndex++;
 | |
| 			else if (index > ranges[insertionIndex-1].maxIndex+1)
 | |
| 			{
 | |
| 				// Insert at end
 | |
| 				ranges.Insert(index, RangeNode<range_type>(index, index), true);
 | |
| 			}
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		if (index < ranges[insertionIndex].minIndex-1)
 | |
| 		{
 | |
| 			// Insert here
 | |
| 			ranges.InsertAtIndex(RangeNode<range_type>(index, index), insertionIndex);
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 		else if (index == ranges[insertionIndex].minIndex-1)
 | |
| 		{
 | |
| 			// Decrease minIndex and join left
 | |
| 			ranges[insertionIndex].minIndex--;
 | |
| 			if (insertionIndex>0 && ranges[insertionIndex-1].maxIndex+1==ranges[insertionIndex].minIndex)
 | |
| 			{
 | |
| 				ranges[insertionIndex-1].maxIndex=ranges[insertionIndex].maxIndex;
 | |
| 				ranges.RemoveAtIndex(insertionIndex);
 | |
| 			}
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 		else if (index >= ranges[insertionIndex].minIndex && index <= ranges[insertionIndex].maxIndex)
 | |
| 		{
 | |
| 			// Already exists
 | |
| 			return;
 | |
| 		}
 | |
| 		else if (index == ranges[insertionIndex].maxIndex+1)
 | |
| 		{
 | |
| 			// Increase maxIndex and join right
 | |
| 			ranges[insertionIndex].maxIndex++;
 | |
| 			if (insertionIndex<ranges.Size()-1 && ranges[insertionIndex+1].minIndex==ranges[insertionIndex].maxIndex+1)
 | |
| 			{
 | |
| 				ranges[insertionIndex+1].minIndex=ranges[insertionIndex].minIndex;
 | |
| 				ranges.RemoveAtIndex(insertionIndex);
 | |
| 			}
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	void RangeList<range_type>::Clear(void)
 | |
| 	{
 | |
| 		ranges.Clear();
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	unsigned RangeList<range_type>::Size(void) const
 | |
| 	{
 | |
| 		return ranges.Size();
 | |
| 	}
 | |
| 
 | |
| 	template <class range_type>
 | |
| 	unsigned RangeList<range_type>::RangeSum(void) const
 | |
| 	{
 | |
| 		unsigned sum=0,i;
 | |
| 		for (i=0; i < ranges.Size(); i++)
 | |
| 			sum+=ranges[i].maxIndex-ranges[i].minIndex+1;
 | |
|         return sum;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 | 
