00001 //---------------------------------------------------------------------------- 00002 /** @file SgArrayList.h 00003 Static list. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef SG_ARRAYLIST_H 00007 #define SG_ARRAYLIST_H 00008 00009 #include <algorithm> 00010 00011 //---------------------------------------------------------------------------- 00012 00013 /** Static list not using dynamic memory allocation. 00014 Elements need to have a default constructor. 00015 They should be value-types, not entity-types, because operations like 00016 Clear() do not call the destructor of the old elements immediately. */ 00017 template<typename T, int SIZE> 00018 class SgArrayList 00019 { 00020 public: 00021 /** Const iterator */ 00022 class Iterator 00023 { 00024 public: 00025 Iterator(const SgArrayList& list); 00026 00027 const T& operator*() const; 00028 00029 void operator++(); 00030 00031 operator bool() const; 00032 00033 private: 00034 const T* m_end; 00035 00036 const T* m_current; 00037 }; 00038 00039 /** Non-const iterator */ 00040 class NonConstIterator 00041 { 00042 public: 00043 NonConstIterator(SgArrayList& list); 00044 00045 T& operator*() const; 00046 00047 void operator++(); 00048 00049 operator bool() const; 00050 00051 private: 00052 const T* m_end; 00053 00054 T* m_current; 00055 }; 00056 00057 SgArrayList(); 00058 00059 /** Construct list with one element. */ 00060 explicit SgArrayList(const T& val); 00061 00062 SgArrayList(const SgArrayList<T,SIZE>& list); 00063 00064 SgArrayList& operator=(const SgArrayList& list); 00065 00066 bool operator==(const SgArrayList& list) const; 00067 00068 bool operator!=(const SgArrayList& list) const; 00069 00070 T& operator[](int index); 00071 00072 const T& operator[](int index) const; 00073 00074 void Clear(); 00075 00076 bool Contains(const T& val) const; 00077 00078 /** Remove first occurrence of a value. 00079 Like RemoveFirst, but more efficient and does not preserve 00080 order of remaining elements. The first occurrence of the value is 00081 replaced by the last element. 00082 @return false, if element was not found */ 00083 bool Exclude(const T& val); 00084 00085 /** PushBack value at the end of the list if it's not already in the 00086 list. */ 00087 void Include(const T& val); 00088 00089 /** Build intersection with other list. 00090 List may not contain duplicate entries. */ 00091 SgArrayList Intersect(const SgArrayList<T,SIZE>& list) const; 00092 00093 bool IsEmpty() const; 00094 00095 T& Last(); 00096 00097 const T& Last() const; 00098 00099 int Length() const; 00100 00101 /** Remove the last element of the list. 00102 Does not return the last element for efficiency. To get the last 00103 element, use Last() before calling PopBack(). */ 00104 void PopBack(); 00105 00106 void PushBack(const T& val); 00107 00108 /** Push back all elements of another list. 00109 Works with lists of different maximum sizes. 00110 Requires: Total resulting number of elements will fit into the target 00111 list. */ 00112 template<int SIZE2> 00113 void PushBackList(const SgArrayList<T,SIZE2>& list); 00114 00115 /** Remove first occurence of a value. 00116 Preserves order of remaining elements. 00117 @see Exclude */ 00118 void RemoveFirst(const T& val); 00119 00120 /** Resize list. 00121 If new length is greater than current length, then the elements 00122 at a place greater than the old length are not initialized, they are 00123 just the old elements at this place. 00124 This is necessary if elements are re-used for efficiency and will be 00125 initialized later. */ 00126 void Resize(int length); 00127 00128 bool SameElements(const SgArrayList& list) const; 00129 00130 void SetTo(const T& val); 00131 00132 void Sort(); 00133 00134 private: 00135 friend class Iterator; 00136 friend class NonConstIterator; 00137 00138 int m_len; 00139 00140 T m_array[SIZE]; 00141 }; 00142 00143 //---------------------------------------------------------------------------- 00144 00145 template<typename T, int SIZE> 00146 inline SgArrayList<T,SIZE>::Iterator::Iterator(const SgArrayList& list) 00147 : m_end(list.m_array + list.Length()), 00148 m_current(list.m_array) 00149 { 00150 } 00151 00152 template<typename T, int SIZE> 00153 inline const T& SgArrayList<T,SIZE>::Iterator::operator*() const 00154 { 00155 SG_ASSERT(*this); 00156 return *m_current; 00157 } 00158 00159 template<typename T, int SIZE> 00160 inline void SgArrayList<T,SIZE>::Iterator::operator++() 00161 { 00162 ++m_current; 00163 } 00164 00165 template<typename T, int SIZE> 00166 inline SgArrayList<T,SIZE>::Iterator::operator bool() const 00167 { 00168 return m_current < m_end; 00169 } 00170 00171 template<typename T, int SIZE> 00172 inline 00173 SgArrayList<T,SIZE>::NonConstIterator::NonConstIterator(SgArrayList& list) 00174 : m_end(list.m_array + list.Length()), 00175 m_current(list.m_array) 00176 { 00177 } 00178 00179 template<typename T, int SIZE> 00180 inline T& SgArrayList<T,SIZE>::NonConstIterator::operator*() const 00181 { 00182 SG_ASSERT(*this); 00183 return *m_current; 00184 } 00185 00186 template<typename T, int SIZE> 00187 inline void SgArrayList<T,SIZE>::NonConstIterator::operator++() 00188 { 00189 ++m_current; 00190 } 00191 00192 template<typename T, int SIZE> 00193 inline SgArrayList<T,SIZE>::NonConstIterator::operator bool() const 00194 { 00195 return m_current < m_end; 00196 } 00197 00198 template<typename T, int SIZE> 00199 inline SgArrayList<T,SIZE>::SgArrayList() 00200 : m_len(0) 00201 { 00202 } 00203 00204 template<typename T, int SIZE> 00205 inline SgArrayList<T,SIZE>::SgArrayList(const T& val) 00206 { 00207 SetTo(val); 00208 m_len = 1; 00209 m_array[0] = val; 00210 } 00211 00212 template<typename T, int SIZE> 00213 inline SgArrayList<T,SIZE>::SgArrayList(const SgArrayList<T,SIZE>& list) 00214 { 00215 *this = list; 00216 } 00217 00218 template<typename T, int SIZE> 00219 SgArrayList<T,SIZE>& SgArrayList<T,SIZE>::operator=(const SgArrayList& list) 00220 { 00221 m_len = list.m_len; 00222 T* p = m_array; 00223 const T* pp = list.m_array; 00224 for (int i = m_len; i--; ++p, ++pp) 00225 *p = *pp; 00226 return *this; 00227 } 00228 00229 template<typename T, int SIZE> 00230 bool SgArrayList<T,SIZE>::operator==(const SgArrayList& list) const 00231 { 00232 if (m_len != list.m_len) 00233 return false; 00234 const T* p = m_array; 00235 const T* pp = list.m_array; 00236 for (int i = m_len; i--; ++p, ++pp) 00237 if (*p != *pp) 00238 return false; 00239 return true; 00240 } 00241 00242 template<typename T, int SIZE> 00243 inline bool SgArrayList<T,SIZE>::operator!=(const SgArrayList& list) const 00244 { 00245 return ! this->operator==(list); 00246 } 00247 00248 template<typename T, int SIZE> 00249 inline T& SgArrayList<T,SIZE>::operator[](int index) 00250 { 00251 SG_ASSERT(index >= 0); 00252 SG_ASSERT(index < m_len); 00253 return m_array[index]; 00254 } 00255 00256 template<typename T, int SIZE> 00257 inline const T& SgArrayList<T,SIZE>::operator[](int index) const 00258 { 00259 SG_ASSERT(index >= 0); 00260 SG_ASSERT(index < m_len); 00261 return m_array[index]; 00262 } 00263 00264 template<typename T, int SIZE> 00265 inline void SgArrayList<T,SIZE>::Clear() 00266 { 00267 m_len = 0; 00268 } 00269 00270 template<typename T, int SIZE> 00271 bool SgArrayList<T,SIZE>::Contains(const T& val) const 00272 { 00273 int i; 00274 const T* t = m_array; 00275 for (i = m_len; i--; ++t) 00276 if (*t == val) 00277 return true; 00278 return false; 00279 } 00280 00281 template<typename T, int SIZE> 00282 bool SgArrayList<T,SIZE>::Exclude(const T& val) 00283 { 00284 // Go backwards through list, because with game playing programs 00285 // it is more likely that a recently added element is removed first 00286 T* t = m_array + m_len - 1; 00287 for (int i = m_len; i--; --t) 00288 if (*t == val) 00289 { 00290 --m_len; 00291 if (m_len > 0) 00292 *t = *(m_array + m_len); 00293 return true; 00294 } 00295 return false; 00296 } 00297 00298 template<typename T, int SIZE> 00299 void SgArrayList<T,SIZE>::Include(const T& val) 00300 { 00301 if (! Contains(val)) 00302 PushBack(val); 00303 } 00304 00305 template<typename T, int SIZE> 00306 SgArrayList<T,SIZE> 00307 SgArrayList<T,SIZE>::Intersect(const SgArrayList<T,SIZE>& list) const 00308 { 00309 SgArrayList<T, SIZE> result; 00310 const T* t = m_array; 00311 for (int i = m_len; i--; ++t) 00312 if (list.Contains(*t)) 00313 { 00314 SG_ASSERT(! result.Contains(*t)); 00315 result.PushBack(*t); 00316 } 00317 return result; 00318 } 00319 00320 template<typename T, int SIZE> 00321 inline bool SgArrayList<T,SIZE>::IsEmpty() const 00322 { 00323 return m_len == 0; 00324 } 00325 00326 template<typename T, int SIZE> 00327 inline T& SgArrayList<T,SIZE>::Last() 00328 { 00329 SG_ASSERT(m_len > 0); 00330 return m_array[m_len - 1]; 00331 } 00332 00333 template<typename T, int SIZE> 00334 inline const T& SgArrayList<T,SIZE>::Last() const 00335 { 00336 SG_ASSERT(m_len > 0); 00337 return m_array[m_len - 1]; 00338 } 00339 00340 template<typename T, int SIZE> 00341 inline int SgArrayList<T,SIZE>::Length() const 00342 { 00343 return m_len; 00344 } 00345 00346 template<typename T, int SIZE> 00347 inline void SgArrayList<T,SIZE>::PopBack() 00348 { 00349 SG_ASSERT(m_len > 0); 00350 --m_len; 00351 } 00352 00353 template<typename T, int SIZE> 00354 inline void SgArrayList<T,SIZE>::PushBack(const T& val) 00355 { 00356 SG_ASSERT(m_len < SIZE); 00357 m_array[m_len++] = val; 00358 } 00359 00360 template<typename T, int SIZE> 00361 template<int SIZE2> 00362 inline void SgArrayList<T,SIZE>::PushBackList(const SgArrayList<T,SIZE2>& list) 00363 { 00364 for (typename SgArrayList<T,SIZE2>::Iterator it(list); it; ++it) 00365 PushBack(*it); 00366 } 00367 00368 template<typename T, int SIZE> 00369 void SgArrayList<T,SIZE>::RemoveFirst(const T& val) 00370 { 00371 int i; 00372 T* t = m_array; 00373 for (i = m_len; i--; ++t) 00374 if (*t == val) 00375 { 00376 for ( ; i--; ++t) 00377 *t = *(t + 1); 00378 --m_len; 00379 break; 00380 } 00381 } 00382 00383 template<typename T, int SIZE> 00384 inline void SgArrayList<T,SIZE>::Resize(int length) 00385 { 00386 SG_ASSERT(length >= 0); 00387 SG_ASSERT(length <= SIZE); 00388 m_len = length; 00389 } 00390 00391 template<typename T, int SIZE> 00392 bool SgArrayList<T,SIZE>::SameElements(const SgArrayList& list) const 00393 { 00394 if (m_len != list.m_len) 00395 return false; 00396 const T* p = m_array; 00397 for (int i = m_len; i--; ++p) 00398 if (! list.Contains(*p)) 00399 return false; 00400 return true; 00401 } 00402 00403 template<typename T, int SIZE> 00404 inline void SgArrayList<T,SIZE>::SetTo(const T& val) 00405 { 00406 m_len = 1; 00407 m_array[0] = val; 00408 } 00409 00410 template<typename T, int SIZE> 00411 inline void SgArrayList<T,SIZE>::Sort() 00412 { 00413 std::sort(m_array, m_array + m_len); 00414 } 00415 00416 //---------------------------------------------------------------------------- 00417 00418 #endif // SG_ARRAYLIST_H