source: trunk/src/array.h @ 1293

Last change on this file since 1293 was 1293, checked in by sam, 9 years ago

core: dynamic arrays can now have up to 8 typed members.

  • Property svn:keywords set to Id
File size: 11.7 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11//
12// The Array class
13// ---------------
14// A very simple Array class not unlike the std::vector, with some nice
15// additional features, eg. Array<int,float> for automatic arrays of structs.
16//
17
18#if !defined __LOL_ARRAY_H__
19#define __LOL_ARRAY_H__
20
21#include <stdint.h>
22
23namespace lol
24{
25
26/*
27 * The base array type
28 * FIXME: only works properly with POD types for now
29 */
30
31template<typename T> class ArrayBase
32{
33public:
34    typedef T Element;
35
36    inline ArrayBase() : m_data(0), m_count(0), m_reserved(0) {}
37    inline ~ArrayBase() { delete[] m_data; }
38
39    ArrayBase(ArrayBase const& that) : m_data(0), m_count(0), m_reserved(0)
40    {
41        Reserve(that.m_reserved);
42        memcpy(m_data, that.m_data, m_count * sizeof(Element));
43        m_count = that.m_count;
44    }
45
46    ArrayBase& operator=(ArrayBase const& that)
47    {
48        m_data = 0;
49        m_count = 0;
50        m_reserved = 0;
51        Reserve(that.m_reserved);
52        memcpy(m_data, that.m_data, that.m_count * sizeof(Element));
53        m_count = that.m_count;
54        return *this;
55    }
56
57    inline Element& operator[](int n)
58    {
59        return m_data[n];
60    }
61
62    inline Element const& operator[](int n) const
63    {
64        return m_data[n];
65    }
66
67    inline ArrayBase<T> const& operator<<(T const &x)
68    {
69        if (m_count >= m_reserved)
70        {
71            T tmp = x;
72            Reserve(m_count * 13 / 8 + 8);
73            m_data[m_count++] = tmp;
74        }
75        else
76        {
77            m_data[m_count++] = x;
78        }
79        return *this;
80    }
81
82    inline void Append(T const &x)
83    {
84        *this << x;
85    }
86
87    void Remove(int pos)
88    {
89        memmove(m_data + pos, m_data + pos + 1, m_count - pos - 1);
90        m_count--;
91    }
92
93    void Remove(int pos, int count)
94    {
95        memmove(m_data + pos, m_data + pos + count, m_count - pos - count);
96        m_count -= count;
97    }
98
99    void Reserve(int count)
100    {
101        if (count <= (int)m_reserved)
102            return;
103
104        Element *tmp = new Element[count];
105        if (m_data)
106        {
107            memcpy(tmp, m_data, m_count * sizeof(Element));
108            delete[] m_data;
109        }
110        m_data = tmp;
111        m_reserved = count;
112    }
113
114    inline int Count() const { return m_count; }
115    inline int Bytes() const { return m_count * sizeof(Element); }
116
117protected:
118    Element *m_data;
119    int m_count, m_reserved;
120};
121
122/*
123 * Element types
124 */
125
126template<typename T1, typename T2, typename T3 = void, typename T4 = void,
127         typename T5 = void, typename T6 = void, typename T7 = void,
128         typename T8 = void>
129class ArrayElement
130{
131public:
132    T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6; T7 m7; T8 m8;
133};
134
135template<typename T1, typename T2, typename T3, typename T4, typename T5,
136         typename T6, typename T7>
137class ArrayElement<T1, T2, T3, T4, T5, T6, T7, void>
138{
139public:
140    T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6; T7 m7;
141};
142
143template<typename T1, typename T2, typename T3, typename T4, typename T5,
144         typename T6>
145class ArrayElement<T1, T2, T3, T4, T5, T6, void, void>
146{
147public:
148    T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6;
149};
150
151template<typename T1, typename T2, typename T3, typename T4, typename T5>
152class ArrayElement<T1, T2, T3, T4, T5, void, void, void>
153{
154public:
155    T1 m1; T2 m2; T3 m3; T4 m4; T5 m5;
156};
157
158template<typename T1, typename T2, typename T3, typename T4>
159class ArrayElement<T1, T2, T3, T4, void, void, void, void>
160{
161public:
162    T1 m1; T2 m2; T3 m3; T4 m4;
163};
164
165template<typename T1, typename T2, typename T3>
166class ArrayElement<T1, T2, T3, void, void, void, void, void>
167{
168public:
169    T1 m1; T2 m2; T3 m3;
170};
171
172template<typename T1, typename T2>
173class ArrayElement<T1, T2, void, void, void, void, void, void>
174{
175public:
176    T1 m1; T2 m2;
177};
178
179/*
180 * Array specialisations implementing specific setters
181 */
182
183template<typename T1, typename T2 = void, typename T3 = void,
184         typename T4 = void, typename T5 = void, typename T6 = void,
185         typename T7 = void, typename T8 = void>
186class Array : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, T7, T8> >
187{
188public:
189    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4,
190                       T5 const &m5, T6 const &m6, T7 const &m7, T8 const &m8)
191    {
192        if (this->m_count >= this->m_reserved)
193        {
194            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4;
195            T5 tmp5 = m5; T6 tmp6 = m6; T7 tmp7 = m7; T8 tmp8 = m8;
196            Reserve(this->m_count * 13 / 8 + 8);
197            this->m_data[this->m_count].m1 = tmp1;
198            this->m_data[this->m_count].m2 = tmp2;
199            this->m_data[this->m_count].m3 = tmp3;
200            this->m_data[this->m_count].m4 = tmp4;
201            this->m_data[this->m_count].m5 = tmp5;
202            this->m_data[this->m_count].m6 = tmp6;
203            this->m_data[this->m_count].m7 = tmp7;
204            this->m_data[this->m_count].m8 = tmp8;
205        }
206        else
207        {
208            this->m_data[this->m_count].m1 = m1;
209            this->m_data[this->m_count].m2 = m2;
210            this->m_data[this->m_count].m3 = m3;
211            this->m_data[this->m_count].m4 = m4;
212            this->m_data[this->m_count].m5 = m5;
213            this->m_data[this->m_count].m6 = m6;
214            this->m_data[this->m_count].m7 = m7;
215            this->m_data[this->m_count].m8 = m8;
216        }
217        ++this->m_count;
218    }
219};
220
221template<typename T1, typename T2, typename T3, typename T4, typename T5,
222         typename T6, typename T7>
223class Array<T1, T2, T3, T4, T5, T6, T7, void>
224  : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, T7, void> >
225{
226public:
227    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4,
228                       T5 const &m5, T6 const &m6, T7 const &m7)
229    {
230        if (this->m_count >= this->m_reserved)
231        {
232            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4;
233            T5 tmp5 = m5; T6 tmp6 = m6; T7 tmp7 = m7;
234            Reserve(this->m_count * 13 / 8 + 8);
235            this->m_data[this->m_count].m1 = tmp1;
236            this->m_data[this->m_count].m2 = tmp2;
237            this->m_data[this->m_count].m3 = tmp3;
238            this->m_data[this->m_count].m4 = tmp4;
239            this->m_data[this->m_count].m5 = tmp5;
240            this->m_data[this->m_count].m6 = tmp6;
241            this->m_data[this->m_count].m7 = tmp7;
242        }
243        else
244        {
245            this->m_data[this->m_count].m1 = m1;
246            this->m_data[this->m_count].m2 = m2;
247            this->m_data[this->m_count].m3 = m3;
248            this->m_data[this->m_count].m4 = m4;
249            this->m_data[this->m_count].m5 = m5;
250            this->m_data[this->m_count].m6 = m6;
251            this->m_data[this->m_count].m7 = m7;
252        }
253        ++this->m_count;
254    }
255};
256
257template<typename T1, typename T2, typename T3, typename T4, typename T5,
258         typename T6>
259class Array<T1, T2, T3, T4, T5, T6, void, void>
260  : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, void, void> >
261{
262public:
263    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4,
264                       T5 const &m5, T6 const &m6)
265    {
266        if (this->m_count >= this->m_reserved)
267        {
268            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4;
269            T5 tmp5 = m5; T6 tmp6 = m6;
270            Reserve(this->m_count * 13 / 8 + 8);
271            this->m_data[this->m_count].m1 = tmp1;
272            this->m_data[this->m_count].m2 = tmp2;
273            this->m_data[this->m_count].m3 = tmp3;
274            this->m_data[this->m_count].m4 = tmp4;
275            this->m_data[this->m_count].m5 = tmp5;
276            this->m_data[this->m_count].m6 = tmp6;
277        }
278        else
279        {
280            this->m_data[this->m_count].m1 = m1;
281            this->m_data[this->m_count].m2 = m2;
282            this->m_data[this->m_count].m3 = m3;
283            this->m_data[this->m_count].m4 = m4;
284            this->m_data[this->m_count].m5 = m5;
285            this->m_data[this->m_count].m6 = m6;
286        }
287        ++this->m_count;
288    }
289};
290
291template<typename T1, typename T2, typename T3, typename T4, typename T5>
292class Array<T1, T2, T3, T4, T5, void, void, void>
293  : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, void, void, void> >
294{
295public:
296    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4,
297                       T5 const &m5)
298    {
299        if (this->m_count >= this->m_reserved)
300        {
301            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4;
302            T5 tmp5 = m5;
303            Reserve(this->m_count * 13 / 8 + 8);
304            this->m_data[this->m_count].m1 = tmp1;
305            this->m_data[this->m_count].m2 = tmp2;
306            this->m_data[this->m_count].m3 = tmp3;
307            this->m_data[this->m_count].m4 = tmp4;
308            this->m_data[this->m_count].m5 = tmp5;
309        }
310        else
311        {
312            this->m_data[this->m_count].m1 = m1;
313            this->m_data[this->m_count].m2 = m2;
314            this->m_data[this->m_count].m3 = m3;
315            this->m_data[this->m_count].m4 = m4;
316            this->m_data[this->m_count].m5 = m5;
317        }
318        ++this->m_count;
319    }
320};
321
322template<typename T1, typename T2, typename T3, typename T4>
323class Array<T1, T2, T3, T4, void, void, void, void>
324  : public ArrayBase<ArrayElement<T1, T2, T3, T4, void, void, void, void> >
325{
326public:
327    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4)
328    {
329        if (this->m_count >= this->m_reserved)
330        {
331            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4;
332            Reserve(this->m_count * 13 / 8 + 8);
333            this->m_data[this->m_count].m1 = tmp1;
334            this->m_data[this->m_count].m2 = tmp2;
335            this->m_data[this->m_count].m3 = tmp3;
336            this->m_data[this->m_count].m4 = tmp4;
337        }
338        else
339        {
340            this->m_data[this->m_count].m1 = m1;
341            this->m_data[this->m_count].m2 = m2;
342            this->m_data[this->m_count].m3 = m3;
343            this->m_data[this->m_count].m4 = m4;
344        }
345        ++this->m_count;
346    }
347};
348
349template<typename T1, typename T2, typename T3>
350class Array<T1, T2, T3, void, void, void, void, void>
351  : public ArrayBase<ArrayElement<T1, T2, T3, void, void, void, void, void> >
352{
353public:
354    inline void Append(T1 const &m1, T2 const &m2, T3 const &m3)
355    {
356        if (this->m_count >= this->m_reserved)
357        {
358            T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3;
359            Reserve(this->m_count * 13 / 8 + 8);
360            this->m_data[this->m_count].m1 = tmp1;
361            this->m_data[this->m_count].m2 = tmp2;
362            this->m_data[this->m_count].m3 = tmp3;
363        }
364        else
365        {
366            this->m_data[this->m_count].m1 = m1;
367            this->m_data[this->m_count].m2 = m2;
368            this->m_data[this->m_count].m3 = m3;
369        }
370        ++this->m_count;
371    }
372};
373
374template<typename T1, typename T2>
375class Array<T1, T2, void, void, void, void, void, void>
376  : public ArrayBase<ArrayElement<T1, T2, void, void, void, void, void, void> >
377{
378public:
379    inline void Append(T1 const &m1, T2 const &m2)
380    {
381        if (this->m_count >= this->m_reserved)
382        {
383            T1 tmp1 = m1; T2 tmp2 = m2;
384            Reserve(this->m_count * 13 / 8 + 8);
385            this->m_data[this->m_count].m1 = tmp1;
386            this->m_data[this->m_count].m2 = tmp2;
387        }
388        else
389        {
390            this->m_data[this->m_count].m1 = m1;
391            this->m_data[this->m_count].m2 = m2;
392        }
393        ++this->m_count;
394    }
395};
396
397template<typename T>
398class Array<T, void, void, void, void, void, void, void> : public ArrayBase<T>
399{
400};
401
402} /* namespace lol */
403
404#endif // __LOL_ARRAY_H__
405
Note: See TracBrowser for help on using the repository browser.