• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

DS_RangeList.h

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __RANGE_LIST_H
00011 #define __RANGE_LIST_H
00012 
00013 #include "DS_OrderedList.h"
00014 #include "BitStream.h"
00015 #include "RakMemoryOverride.h"
00016 #include "RakAssert.h"
00017 
00018 namespace DataStructures
00019 {
00020         template <class range_type>
00021         struct RangeNode
00022     {
00023         RangeNode() {}
00024         ~RangeNode() {}
00025         RangeNode(range_type min, range_type max) {minIndex=min; maxIndex=max;}
00026         range_type minIndex;
00027         range_type maxIndex;
00028     };
00029 
00030 
00031     template <class range_type>
00032     int RangeNodeComp(const range_type &a, const RangeNode<range_type> &b)
00033     {
00034         if (a<b.minIndex)
00035             return -1;
00036         if (a==b.minIndex)
00037             return 0;
00038         return 1;
00039     }
00040 
00041         template <class range_type>
00042         class RAK_DLL_EXPORT RangeList
00043         {
00044         public:
00045                 RangeList();
00046                 ~RangeList();
00047                 void Insert(range_type index);
00048                 void Clear(void);
00049                 unsigned Size(void) const;
00050                 unsigned RangeSum(void) const;
00051                 BitSize_t Serialize(RakNet::BitStream *in, BitSize_t maxBits, bool clearSerialized);
00052                 bool Deserialize(RakNet::BitStream *out);
00053 
00054                 DataStructures::OrderedList<range_type, RangeNode<range_type> , RangeNodeComp<range_type> > ranges;
00055         };
00056 
00057         template <class range_type>
00058         BitSize_t RangeList<range_type>::Serialize(RakNet::BitStream *in, BitSize_t maxBits, bool clearSerialized)
00059         {
00060                 RakAssert(ranges.Size() < (unsigned short)-1);
00061                 RakNet::BitStream tempBS;
00062                 BitSize_t bitsWritten;
00063                 unsigned short countWritten;
00064                 unsigned i;
00065                 countWritten=0;
00066                 bitsWritten=0;
00067                 for (i=0; i < ranges.Size(); i++)
00068                 {
00069                         if ((int)sizeof(unsigned short)*8+bitsWritten+(int)sizeof(range_type)*8*2+1>maxBits)
00070                                 break;
00071                         unsigned char minEqualsMax;
00072                         if (ranges[i].minIndex==ranges[i].maxIndex)
00073                                 minEqualsMax=1;
00074                         else
00075                                 minEqualsMax=0;
00076                         tempBS.Write(minEqualsMax); // Use one byte, intead of one bit, for speed, as this is done a lot
00077                         tempBS.Write(ranges[i].minIndex);
00078                         bitsWritten+=sizeof(range_type)*8+8;
00079                         if (ranges[i].minIndex!=ranges[i].maxIndex)
00080                         {
00081                                 tempBS.Write(ranges[i].maxIndex);
00082                                 bitsWritten+=sizeof(range_type)*8;
00083                         }
00084                         countWritten++;
00085                 }
00086 
00087                 in->AlignWriteToByteBoundary();
00088                 BitSize_t before=in->GetWriteOffset();
00089                 in->Write(countWritten);
00090                 bitsWritten+=in->GetWriteOffset()-before;
00091         //      RAKNET_DEBUG_PRINTF("%i ", in->GetNumberOfBitsUsed());
00092                 in->Write(&tempBS, tempBS.GetNumberOfBitsUsed());
00093         //      RAKNET_DEBUG_PRINTF("%i %i \n", tempBS.GetNumberOfBitsUsed(),in->GetNumberOfBitsUsed());
00094 
00095                 if (clearSerialized && countWritten)
00096                 {
00097                         unsigned rangeSize=ranges.Size();
00098                         for (i=0; i < rangeSize-countWritten; i++)
00099                         {
00100                                 ranges[i]=ranges[i+countWritten];
00101                         }
00102                         ranges.RemoveFromEnd(countWritten);
00103                 }
00104 
00105                 return bitsWritten;
00106         }
00107         template <class range_type>
00108         bool RangeList<range_type>::Deserialize(RakNet::BitStream *out)
00109         {
00110                 ranges.Clear(true, __FILE__, __LINE__);
00111                 unsigned short count;
00112                 out->AlignReadToByteBoundary();
00113                 out->Read(count);
00114                 unsigned short i;
00115                 range_type min,max;
00116                 unsigned char maxEqualToMin=0;
00117 
00118                 for (i=0; i < count; i++)
00119                 {
00120                         out->Read(maxEqualToMin);
00121                         if (out->Read(min)==false)
00122                                 return false;
00123                         if (maxEqualToMin==false)
00124                         {
00125                                 if (out->Read(max)==false)
00126                                         return false;
00127                                 if (max<min)
00128                                         return false;
00129                         }
00130                         else
00131                                 max=min;
00132 
00133 
00134                         ranges.InsertAtEnd(RangeNode<range_type>(min,max), __FILE__,__LINE__);
00135                 }
00136                 return true;
00137         }
00138 
00139         template <class range_type>
00140         RangeList<range_type>::RangeList()
00141         {
00142                 RangeNodeComp<range_type>(0, RangeNode<range_type>());
00143         }
00144 
00145         template <class range_type>
00146         RangeList<range_type>::~RangeList()
00147         {
00148                 Clear();
00149         }
00150 
00151         template <class range_type>
00152         void RangeList<range_type>::Insert(range_type index)
00153         {
00154                 if (ranges.Size()==0)
00155                 {
00156                         ranges.Insert(index, RangeNode<range_type>(index, index), true, __FILE__,__LINE__);
00157                         return;
00158                 }
00159 
00160                 bool objectExists;
00161                 unsigned insertionIndex=ranges.GetIndexFromKey(index, &objectExists);
00162                 if (insertionIndex==ranges.Size())
00163                 {
00164                         if (index == ranges[insertionIndex-1].maxIndex+(range_type)1)
00165                                 ranges[insertionIndex-1].maxIndex++;
00166                         else if (index > ranges[insertionIndex-1].maxIndex+(range_type)1)
00167                         {
00168                                 // Insert at end
00169                                 ranges.Insert(index, RangeNode<range_type>(index, index), true, __FILE__,__LINE__);
00170                         }
00171 
00172                         return;
00173                 }
00174 
00175                 if (index < ranges[insertionIndex].minIndex-(range_type)1)
00176                 {
00177                         // Insert here
00178                         ranges.InsertAtIndex(RangeNode<range_type>(index, index), insertionIndex, __FILE__,__LINE__);
00179 
00180                         return;
00181                 }
00182                 else if (index == ranges[insertionIndex].minIndex-(range_type)1)
00183                 {
00184                         // Decrease minIndex and join left
00185                         ranges[insertionIndex].minIndex--;
00186                         if (insertionIndex>0 && ranges[insertionIndex-1].maxIndex+(range_type)1==ranges[insertionIndex].minIndex)
00187                         {
00188                                 ranges[insertionIndex-1].maxIndex=ranges[insertionIndex].maxIndex;
00189                                 ranges.RemoveAtIndex(insertionIndex);
00190                         }
00191 
00192                         return;
00193                 }
00194                 else if (index >= ranges[insertionIndex].minIndex && index <= ranges[insertionIndex].maxIndex)
00195                 {
00196                         // Already exists
00197                         return;
00198                 }
00199                 else if (index == ranges[insertionIndex].maxIndex+(range_type)1)
00200                 {
00201                         // Increase maxIndex and join right
00202                         ranges[insertionIndex].maxIndex++;
00203                         if (insertionIndex<ranges.Size()-1 && ranges[insertionIndex+(range_type)1].minIndex==ranges[insertionIndex].maxIndex+(range_type)1)
00204                         {
00205                                 ranges[insertionIndex+1].minIndex=ranges[insertionIndex].minIndex;
00206                                 ranges.RemoveAtIndex(insertionIndex);
00207                         }
00208 
00209                         return;
00210                 }
00211         }
00212 
00213         template <class range_type>
00214         void RangeList<range_type>::Clear(void)
00215         {
00216                 ranges.Clear(true, __FILE__, __LINE__);
00217         }
00218 
00219         template <class range_type>
00220         unsigned RangeList<range_type>::Size(void) const
00221         {
00222                 return ranges.Size();
00223         }
00224 
00225         template <class range_type>
00226         unsigned RangeList<range_type>::RangeSum(void) const
00227         {
00228                 unsigned sum=0,i;
00229                 for (i=0; i < ranges.Size(); i++)
00230                         sum+=ranges[i].maxIndex-ranges[i].minIndex+1;
00231         return sum;
00232         }
00233 
00234 }
00235 
00236 #endif

Generated on Thu Sep 30 2010 01:27:23 for RakNet by  doxygen 1.7.1