Shadowrun: Awakened 29 September 2011 - Build 871
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         RakNet::BitSize_t Serialize(RakNet::BitStream *in, RakNet::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     RakNet::BitSize_t RangeList<range_type>::Serialize(RakNet::BitStream *in, RakNet::BitSize_t maxBits, bool clearSerialized)
00059     {
00060         RakAssert(ranges.Size() < (unsigned short)-1);
00061         RakNet::BitStream tempBS;
00062         RakNet::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         RakNet::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_AND_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_AND_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_AND_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_AND_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_AND_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_AND_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

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net