[ATL][ATL_APITEST] Implemente CSimpleArray + CSimpleMap. Based on a patch from Kataya...
[reactos.git] / reactos / 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 m_nCapacity = src.GetSize();
186
187 T *pNewData = (T *)realloc(m_pData, m_nCapacity * sizeof(T));
188 ATLASSERT(pNewData);
189 if (pNewData == NULL)
190 return *this; // failure
191
192 // store new data and capacity
193 m_pData = pNewData;
194 m_nCount = m_nCapacity;
195 }
196 else
197 {
198 for (int nIndex = 0; nIndex < m_nCount; ++nIndex)
199 {
200 DestructItem(nIndex);
201 }
202 }
203
204 ATLASSERT(GetSize() == src.GetSize());
205 for (int nIndex = 0; nIndex < src.GetSize(); ++nIndex)
206 {
207 ConstructItemInPlace(nIndex, src[nIndex]);
208 }
209
210 return *this;
211 }
212
213 protected:
214 T * m_pData; // malloc'ed
215 int m_nCount; // # of items of type T
216 int m_nCapacity; // for optimization
217 static const int c_nGrow = 8; // for optimization
218
219 // NOTE: Range m_pData[0] .. m_pData[m_nCapacity - 1] are accessible.
220 // NOTE: Range [0, m_nCount) are constructed.
221 // NOTE: Range [m_nCount, m_nCapacity) are not constructed.
222 // NOTE: 0 <= m_nCount && m_nCount <= m_nCapacity.
223
224 // call constructor at nIndex
225 void ConstructItemInPlace(int nIndex, const T& src)
226 {
227 new(&m_pData[nIndex]) ConstructImpl(src);
228 }
229
230 // call destructor at nIndex
231 void DestructItem(int nIndex)
232 {
233 m_pData[nIndex].~T();
234 }
235
236 private:
237
238 struct ConstructImpl
239 {
240 ConstructImpl(const T& obj)
241 :m_ConstructHelper(obj)
242 {
243 }
244
245 static void *operator new(size_t, void *ptr)
246 {
247 return ptr;
248 }
249
250 static void operator delete(void *p, void* )
251 {
252 }
253
254 T m_ConstructHelper;
255 };
256
257 };
258
259 template <typename TKey, typename TVal>
260 class CSimpleMapEqualHelper
261 {
262 public:
263 static bool IsEqualKey(const TKey& k1, const TKey& k2)
264 {
265 return k1 == k2;
266 }
267
268 static bool IsEqualValue(const TVal& v1, const TVal& v2)
269 {
270 return v1 == v2;
271 }
272 };
273
274 // This class exists for the keys and the values of no comparison.
275 template <typename TKey, typename TVal>
276 class CSimpleMapEqualHelperFalse
277 {
278 public:
279 static bool IsEqualKey(const TKey& k1, const TKey& k2)
280 {
281 ATLASSERT(FALSE);
282 return false;
283 }
284
285 static bool IsEqualValue(const TVal& v1, const TVal& v2)
286 {
287 ATLASSERT(FALSE);
288 return false;
289 }
290 };
291
292 template <typename TKey, typename TVal,
293 typename TEqual = CSimpleMapEqualHelper<TKey, TVal> >
294 class CSimpleMap
295 {
296 public:
297 typedef TKey _ArrayKeyType;
298 typedef TVal _ArrayElementType;
299
300 CSimpleMap()
301 {
302 }
303
304 ~CSimpleMap()
305 {
306 }
307
308 BOOL Add(const TKey& key, const TVal& val)
309 {
310 Pair pair(key, val);
311 return m_Pairs.Add(pair);
312 }
313
314 int FindKey(const TKey& key) const
315 {
316 const int nCount = GetSize();
317 for (int nIndex = 0; nIndex < nCount; ++nIndex)
318 {
319 if (TEqual::IsEqualKey(m_Pairs[nIndex].key, key))
320 {
321 return nIndex; // success
322 }
323 }
324 return -1; // failure
325 }
326
327 int FindVal(const TVal& val) const
328 {
329 const int nCount = GetSize();
330 for (int nIndex = 0; nIndex < nCount; ++nIndex)
331 {
332 if (TEqual::IsEqualValue(m_Pairs[nIndex].val, val))
333 {
334 return nIndex; // success
335 }
336 }
337 return -1; // failure
338 }
339
340 TKey& GetKeyAt(int nIndex)
341 {
342 ATLASSERT(0 <= nIndex && nIndex < GetSize());
343 return m_Pairs[nIndex].key;
344 }
345
346 const TKey& GetKeyAt(int nIndex) const
347 {
348 ATLASSERT(0 <= nIndex && nIndex < GetSize());
349 return m_Pairs[nIndex].key;
350 }
351
352 int GetSize() const
353 {
354 return m_Pairs.GetSize();
355 }
356
357 TVal& GetValueAt(int nIndex)
358 {
359 ATLASSERT(0 <= nIndex && nIndex < GetSize());
360 return m_Pairs[nIndex].val;
361 }
362
363 const TVal& GetValueAt(int nIndex) const
364 {
365 ATLASSERT(0 <= nIndex && nIndex < GetSize());
366 return m_Pairs[nIndex].val;
367 }
368
369 TVal Lookup(const TKey& key) const
370 {
371 int nIndex = FindKey(key);
372 if (nIndex < 0)
373 return TVal();
374 return m_Pairs[nIndex].val;
375 }
376
377 BOOL Remove(const TKey& key)
378 {
379 int nIndex = FindKey(key);
380 return RemoveAt(nIndex);
381 }
382
383 void RemoveAll()
384 {
385 m_Pairs.RemoveAll();
386 }
387
388 BOOL RemoveAt(int nIndex)
389 {
390 return m_Pairs.RemoveAt(nIndex);
391 }
392
393 TKey ReverseLookup(const TVal& val) const
394 {
395 int nIndex = FindVal(val);
396 if (nIndex < 0)
397 return TKey();
398 return m_Pairs[nIndex].key;
399 }
400
401 BOOL SetAt(const TKey& key, const TVal& val)
402 {
403 int nIndex = FindKey(key);
404 if (nIndex < 0)
405 return Add(key, val);
406
407 m_Pairs[nIndex].val = val;
408 return TRUE;
409 }
410
411 BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val)
412 {
413 // boundary check
414 if (nIndex < 0 || GetSize() <= nIndex)
415 return FALSE;
416
417 m_Pairs[nIndex].key = key;
418 m_Pairs[nIndex].val = val;
419 return TRUE;
420 }
421
422 protected:
423 struct Pair
424 {
425 TKey key;
426 TVal val;
427
428 Pair()
429 {
430 }
431
432 Pair(const TKey& k, const TVal& v) : key(k), val(v)
433 {
434 }
435
436 Pair(const Pair& pair) : key(pair.key), val(pair.val)
437 {
438 }
439
440 Pair& operator=(const Pair& pair)
441 {
442 key = pair.key;
443 val = pair.val;
444 return *this;
445 }
446 };
447
448 CSimpleArray<Pair, CSimpleArrayEqualHelperFalse<Pair> > m_Pairs;
449 };
450
451 }
452
453 #endif