[ATL] Improve the order of operations in CComPtr and CComQIIDPtr
[reactos.git] / sdk / lib / atl / atlsimpcoll.h
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:
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:
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
43 CSimpleArray() : m_pData(NULL), m_nCount(0), m_nCapacity(0)
44 {
45 }
46
47 CSimpleArray(const CSimpleArray<T, TEqual>& src) :
48 m_pData(NULL), m_nCount(0), m_nCapacity(0)
49 {
50 *this = src;
51 }
52
53 ~CSimpleArray()
54 {
55 RemoveAll();
56 }
57
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(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
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
94 T* GetData()
95 {
96 return m_pData;
97 }
98
99 const T* GetData() const
100 {
101 return m_pData;
102 }
103
104 int GetSize() const
105 {
106 return m_nCount;
107 }
108
109 BOOL Remove(const T& t)
110 {
111 return RemoveAt(Find(t));
112 }
113
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
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(&m_pData[nIndex], &m_pData[nIndex + 1], nRightSize);
145
146 // decrement
147 --m_nCount;
148
149 return TRUE;
150 }
151
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(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
226 void ConstructItemInPlace(int nIndex, const T& src)
227 {
228 new(&m_pData[nIndex]) ConstructImpl(src);
229 }
230
231 // call destructor at nIndex
232 void DestructItem(int nIndex)
233 {
234 m_pData[nIndex].~T();
235 }
236
237 private:
238
239 struct ConstructImpl
240 {
241 ConstructImpl(const T& obj)
242 :m_ConstructHelper(obj)
243 {
244 }
245
246 static void *operator new(size_t, void *ptr)
247 {
248 return ptr;
249 }
250
251 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:
264 static bool IsEqualKey(const TKey& k1, const TKey& k2)
265 {
266 return k1 == k2;
267 }
268
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:
280 static bool IsEqualKey(const TKey& k1, const TKey& k2)
281 {
282 ATLASSERT(FALSE);
283 return false;
284 }
285
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
301 CSimpleMap()
302 {
303 }
304
305 ~CSimpleMap()
306 {
307 }
308
309 BOOL Add(const TKey& key, const TVal& val)
310 {
311 Pair pair(key, val);
312 return m_Pairs.Add(pair);
313 }
314
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
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
341 TKey& GetKeyAt(int nIndex)
342 {
343 ATLASSERT(0 <= nIndex && nIndex < GetSize());
344 return m_Pairs[nIndex].key;
345 }
346
347 const TKey& GetKeyAt(int nIndex) const
348 {
349 ATLASSERT(0 <= nIndex && nIndex < GetSize());
350 return m_Pairs[nIndex].key;
351 }
352
353 int GetSize() const
354 {
355 return m_Pairs.GetSize();
356 }
357
358 TVal& GetValueAt(int nIndex)
359 {
360 ATLASSERT(0 <= nIndex && nIndex < GetSize());
361 return m_Pairs[nIndex].val;
362 }
363
364 const TVal& GetValueAt(int nIndex) const
365 {
366 ATLASSERT(0 <= nIndex && nIndex < GetSize());
367 return m_Pairs[nIndex].val;
368 }
369
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
378 BOOL Remove(const TKey& key)
379 {
380 int nIndex = FindKey(key);
381 return RemoveAt(nIndex);
382 }
383
384 void RemoveAll()
385 {
386 m_Pairs.RemoveAll();
387 }
388
389 BOOL RemoveAt(int nIndex)
390 {
391 return m_Pairs.RemoveAt(nIndex);
392 }
393
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
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
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
429 Pair()
430 {
431 }
432
433 Pair(const TKey& k, const TVal& v) : key(k), val(v)
434 {
435 }
436
437 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