![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.