xref: /reactos/sdk/lib/atl/atlsimpcoll.h (revision 48f3efa2)
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