xref: /reactos/sdk/lib/atl/atlsimpcoll.h (revision ebaf247c)
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(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 
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(static_cast<void *>(&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(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
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
455