1 // PROJECT: ReactOS ATL Simple Collection 2 // LICENSE: Public Domain 3 // PURPOSE: Provides compatibility to Microsoft ATL 4 // PROGRAMMERS: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 5 6 #ifndef __ATLSIMPCOLL_H__ 7 #define __ATLSIMPCOLL_H__ 8 9 #pragma once 10 11 #include "atlcore.h" // for ATL Core 12 13 namespace ATL 14 { 15 template <typename T> 16 class CSimpleArrayEqualHelper 17 { 18 public: IsEqual(const T & t1,const T & t2)19 static bool IsEqual(const T& t1, const T& t2) 20 { 21 return t1 == t2; 22 } 23 }; 24 25 // This class exists for the element types of no comparison. 26 template <typename T> 27 class CSimpleArrayEqualHelperFalse 28 { 29 public: IsEqual(const T &,const T &)30 static bool IsEqual(const T&, const T&) 31 { 32 ATLASSERT(FALSE); 33 return false; 34 } 35 }; 36 37 template <typename T, typename TEqual = CSimpleArrayEqualHelper<T> > 38 class CSimpleArray 39 { 40 public: 41 typedef T _ArrayElementType; 42 CSimpleArray()43 CSimpleArray() : m_pData(NULL), m_nCount(0), m_nCapacity(0) 44 { 45 } 46 CSimpleArray(const CSimpleArray<T,TEqual> & src)47 CSimpleArray(const CSimpleArray<T, TEqual>& src) : 48 m_pData(NULL), m_nCount(0), m_nCapacity(0) 49 { 50 *this = src; 51 } 52 ~CSimpleArray()53 ~CSimpleArray() 54 { 55 RemoveAll(); 56 } 57 Add(const T & t)58 BOOL Add(const T& t) 59 { 60 // is the capacity enough? 61 if (m_nCapacity < m_nCount + 1) 62 { 63 // allocate extra capacity for optimization 64 const int nNewCapacity = (m_nCount + 1) + c_nGrow; 65 T *pNewData = (T *)realloc(static_cast<void *>(m_pData), nNewCapacity * sizeof(T)); 66 if (pNewData == NULL) 67 return FALSE; // failure 68 69 m_pData = pNewData; 70 m_nCapacity = nNewCapacity; 71 } 72 73 // call constructor 74 ConstructItemInPlace(m_nCount, t); 75 76 // increment 77 ++m_nCount; 78 79 return TRUE; 80 } 81 Find(const T & t)82 int Find(const T& t) const 83 { 84 for (int nIndex = 0; nIndex < m_nCount; ++nIndex) 85 { 86 if (TEqual::IsEqual(m_pData[nIndex], t)) 87 { 88 return nIndex; // success 89 } 90 } 91 return -1; // failure 92 } 93 GetData()94 T* GetData() 95 { 96 return m_pData; 97 } 98 GetData()99 const T* GetData() const 100 { 101 return m_pData; 102 } 103 GetSize()104 int GetSize() const 105 { 106 return m_nCount; 107 } 108 Remove(const T & t)109 BOOL Remove(const T& t) 110 { 111 return RemoveAt(Find(t)); 112 } 113 RemoveAll()114 void RemoveAll() 115 { 116 if (m_pData) 117 { 118 // call destructor 119 const int nCount = m_nCount; 120 for (int nIndex = 0; nIndex < nCount; ++nIndex) 121 { 122 DestructItem(nIndex); 123 } 124 125 free(m_pData); 126 m_pData = NULL; 127 } 128 m_nCount = 0; 129 m_nCapacity = 0; 130 } 131 RemoveAt(int nIndex)132 BOOL RemoveAt(int nIndex) 133 { 134 // boundary check 135 if (nIndex < 0 || m_nCount <= nIndex) 136 return FALSE; // failure 137 138 // call destructor 139 DestructItem(nIndex); 140 141 // move range [nIndex + 1, m_nCount) to nIndex 142 const int nRightCount = m_nCount - (nIndex + 1); 143 const int nRightSize = nRightCount * sizeof(T); 144 memmove(static_cast<void *>(&m_pData[nIndex]), &m_pData[nIndex + 1], nRightSize); 145 146 // decrement 147 --m_nCount; 148 149 return TRUE; 150 } 151 SetAtIndex(int nIndex,const T & t)152 BOOL SetAtIndex(int nIndex, const T& t) 153 { 154 // boundary check 155 if (nIndex < 0 || m_nCount <= nIndex) 156 return FALSE; // failure 157 158 // store it 159 m_pData[nIndex] = t; 160 return TRUE; 161 } 162 163 T& operator[](int nIndex) 164 { 165 ATLASSERT(0 <= nIndex && nIndex < m_nCount); 166 return m_pData[nIndex]; 167 } 168 169 const T& operator[](int nIndex) const 170 { 171 ATLASSERT(0 <= nIndex && nIndex < m_nCount); 172 return m_pData[nIndex]; 173 } 174 175 CSimpleArray<T, TEqual>& operator=(const CSimpleArray<T, TEqual>& src) 176 { 177 // don't copy if two objects are same 178 if (this == &src) 179 return *this; 180 181 if (src.GetSize() != GetSize()) 182 { 183 RemoveAll(); 184 185 int nNewCount = src.GetSize(); 186 187 T *pNewData = (T *)realloc(static_cast<void *>(m_pData), nNewCount * sizeof(T)); 188 ATLASSERT(pNewData); 189 if (pNewData == NULL) 190 return *this; // failure 191 192 // store new 193 m_pData = pNewData; 194 m_nCount = nNewCount; 195 m_nCapacity = nNewCount; 196 } 197 else 198 { 199 for (int nIndex = 0; nIndex < m_nCount; ++nIndex) 200 { 201 DestructItem(nIndex); 202 } 203 } 204 205 ATLASSERT(GetSize() == src.GetSize()); 206 for (int nIndex = 0; nIndex < src.GetSize(); ++nIndex) 207 { 208 ConstructItemInPlace(nIndex, src[nIndex]); 209 } 210 211 return *this; 212 } 213 214 protected: 215 T * m_pData; // malloc'ed 216 int m_nCount; // # of items of type T 217 int m_nCapacity; // for optimization 218 static const int c_nGrow = 8; // for optimization 219 220 // NOTE: Range m_pData[0] .. m_pData[m_nCapacity - 1] are accessible. 221 // NOTE: Range [0, m_nCount) are constructed. 222 // NOTE: Range [m_nCount, m_nCapacity) are not constructed. 223 // NOTE: 0 <= m_nCount && m_nCount <= m_nCapacity. 224 225 // call constructor at nIndex ConstructItemInPlace(int nIndex,const T & src)226 void ConstructItemInPlace(int nIndex, const T& src) 227 { 228 new(&m_pData[nIndex]) ConstructImpl(src); 229 } 230 231 // call destructor at nIndex DestructItem(int nIndex)232 void DestructItem(int nIndex) 233 { 234 m_pData[nIndex].~T(); 235 } 236 237 private: 238 239 struct ConstructImpl 240 { ConstructImplConstructImpl241 ConstructImpl(const T& obj) 242 :m_ConstructHelper(obj) 243 { 244 } 245 newConstructImpl246 static void *operator new(size_t, void *ptr) 247 { 248 return ptr; 249 } 250 deleteConstructImpl251 static void operator delete(void *p, void* ) 252 { 253 } 254 255 T m_ConstructHelper; 256 }; 257 258 }; 259 260 template <typename TKey, typename TVal> 261 class CSimpleMapEqualHelper 262 { 263 public: IsEqualKey(const TKey & k1,const TKey & k2)264 static bool IsEqualKey(const TKey& k1, const TKey& k2) 265 { 266 return k1 == k2; 267 } 268 IsEqualValue(const TVal & v1,const TVal & v2)269 static bool IsEqualValue(const TVal& v1, const TVal& v2) 270 { 271 return v1 == v2; 272 } 273 }; 274 275 // This class exists for the keys and the values of no comparison. 276 template <typename TKey, typename TVal> 277 class CSimpleMapEqualHelperFalse 278 { 279 public: IsEqualKey(const TKey & k1,const TKey & k2)280 static bool IsEqualKey(const TKey& k1, const TKey& k2) 281 { 282 ATLASSERT(FALSE); 283 return false; 284 } 285 IsEqualValue(const TVal & v1,const TVal & v2)286 static bool IsEqualValue(const TVal& v1, const TVal& v2) 287 { 288 ATLASSERT(FALSE); 289 return false; 290 } 291 }; 292 293 template <typename TKey, typename TVal, 294 typename TEqual = CSimpleMapEqualHelper<TKey, TVal> > 295 class CSimpleMap 296 { 297 public: 298 typedef TKey _ArrayKeyType; 299 typedef TVal _ArrayElementType; 300 CSimpleMap()301 CSimpleMap() 302 { 303 } 304 ~CSimpleMap()305 ~CSimpleMap() 306 { 307 } 308 Add(const TKey & key,const TVal & val)309 BOOL Add(const TKey& key, const TVal& val) 310 { 311 Pair pair(key, val); 312 return m_Pairs.Add(pair); 313 } 314 FindKey(const TKey & key)315 int FindKey(const TKey& key) const 316 { 317 const int nCount = GetSize(); 318 for (int nIndex = 0; nIndex < nCount; ++nIndex) 319 { 320 if (TEqual::IsEqualKey(m_Pairs[nIndex].key, key)) 321 { 322 return nIndex; // success 323 } 324 } 325 return -1; // failure 326 } 327 FindVal(const TVal & val)328 int FindVal(const TVal& val) const 329 { 330 const int nCount = GetSize(); 331 for (int nIndex = 0; nIndex < nCount; ++nIndex) 332 { 333 if (TEqual::IsEqualValue(m_Pairs[nIndex].val, val)) 334 { 335 return nIndex; // success 336 } 337 } 338 return -1; // failure 339 } 340 GetKeyAt(int nIndex)341 TKey& GetKeyAt(int nIndex) 342 { 343 ATLASSERT(0 <= nIndex && nIndex < GetSize()); 344 return m_Pairs[nIndex].key; 345 } 346 GetKeyAt(int nIndex)347 const TKey& GetKeyAt(int nIndex) const 348 { 349 ATLASSERT(0 <= nIndex && nIndex < GetSize()); 350 return m_Pairs[nIndex].key; 351 } 352 GetSize()353 int GetSize() const 354 { 355 return m_Pairs.GetSize(); 356 } 357 GetValueAt(int nIndex)358 TVal& GetValueAt(int nIndex) 359 { 360 ATLASSERT(0 <= nIndex && nIndex < GetSize()); 361 return m_Pairs[nIndex].val; 362 } 363 GetValueAt(int nIndex)364 const TVal& GetValueAt(int nIndex) const 365 { 366 ATLASSERT(0 <= nIndex && nIndex < GetSize()); 367 return m_Pairs[nIndex].val; 368 } 369 Lookup(const TKey & key)370 TVal Lookup(const TKey& key) const 371 { 372 int nIndex = FindKey(key); 373 if (nIndex < 0) 374 return TVal(); 375 return m_Pairs[nIndex].val; 376 } 377 Remove(const TKey & key)378 BOOL Remove(const TKey& key) 379 { 380 int nIndex = FindKey(key); 381 return RemoveAt(nIndex); 382 } 383 RemoveAll()384 void RemoveAll() 385 { 386 m_Pairs.RemoveAll(); 387 } 388 RemoveAt(int nIndex)389 BOOL RemoveAt(int nIndex) 390 { 391 return m_Pairs.RemoveAt(nIndex); 392 } 393 ReverseLookup(const TVal & val)394 TKey ReverseLookup(const TVal& val) const 395 { 396 int nIndex = FindVal(val); 397 if (nIndex < 0) 398 return TKey(); 399 return m_Pairs[nIndex].key; 400 } 401 SetAt(const TKey & key,const TVal & val)402 BOOL SetAt(const TKey& key, const TVal& val) 403 { 404 int nIndex = FindKey(key); 405 if (nIndex < 0) 406 return Add(key, val); 407 408 m_Pairs[nIndex].val = val; 409 return TRUE; 410 } 411 SetAtIndex(int nIndex,const TKey & key,const TVal & val)412 BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val) 413 { 414 // boundary check 415 if (nIndex < 0 || GetSize() <= nIndex) 416 return FALSE; 417 418 m_Pairs[nIndex].key = key; 419 m_Pairs[nIndex].val = val; 420 return TRUE; 421 } 422 423 protected: 424 struct Pair 425 { 426 TKey key; 427 TVal val; 428 PairPair429 Pair() 430 { 431 } 432 PairPair433 Pair(const TKey& k, const TVal& v) : key(k), val(v) 434 { 435 } 436 PairPair437 Pair(const Pair& pair) : key(pair.key), val(pair.val) 438 { 439 } 440 441 Pair& operator=(const Pair& pair) 442 { 443 key = pair.key; 444 val = pair.val; 445 return *this; 446 } 447 }; 448 449 CSimpleArray<Pair, CSimpleArrayEqualHelperFalse<Pair> > m_Pairs; 450 }; 451 452 } 453 454 #endif 455