-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSmallVector.h
More file actions
134 lines (103 loc) · 3.31 KB
/
SmallVector.h
File metadata and controls
134 lines (103 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// A dynamic vector optimized for small elements and size
// Copyright (C) 2014 Jens Jacob Støren
// Can be used under the GNU General Public License v3.0
// If that license does not fit, please contact the author.
#ifndef SMALLVECTOR_H
#define SMALLVECTOR_H
#include <cstring>
// #pragma pack(1) // Use to minimize memory fotprint at the cost of some speed
template <typename Element, unsigned char embeddedElementCount>
class SmallVector
{
public:
SmallVector() : m_elmArray(0), m_size(0) {}
~SmallVector()
{
resize(0);
}
void resize(unsigned char newSize)
{
if (newSize == m_size) return;
runDestructorForUnnecessaryObjects(newSize);
void * newData = allocateNewData(newSize);
copyOldDataIntoNewData(newData, newSize);
runConstructorsForNewElements(newData, newSize);
freeOldDataAndUseNew(newData, newSize);
}
Element& operator[] (unsigned char idx) { if ( m_size <= embeddedElementCount ) { return (reinterpret_cast<Element*>(m_elmData))[static_cast<unsigned short> (idx)]; } else {return m_elmArray[static_cast<unsigned short> (idx)]; } }
void push_back(const Element& elm) { unsigned char newIdx = m_size; this->resize(m_size + 1); (*this)[newIdx] = elm; }
unsigned char size() { return m_size; }
void clear() { resize(0); }
private:
void runDestructorForUnnecessaryObjects(unsigned char newSize)
{
if (newSize >= m_size) return;
Element* objectsToDelete = NULL;
if (embeddedElementCount < m_size )
{
objectsToDelete = m_elmArray;
}
else
{
objectsToDelete = reinterpret_cast<Element*> (m_elmData);
}
for (int i = newSize; i < m_size; ++i)
{
(&(objectsToDelete[i]))->~Element();
}
}
void * allocateNewData(unsigned char newSize)
{
if (newSize == 0) return NULL;
void * newData = NULL;
if (newSize > embeddedElementCount)
{
newData = ::operator new (newSize * sizeof(Element));
}
else
{
newData = reinterpret_cast<void*>(m_elmData);
}
return newData;
}
void copyOldDataIntoNewData(void * newData, unsigned char newSize)
{
if (m_size == 0 || newSize == 0) return;
size_t minElmCount = newSize > m_size ? m_size: newSize;
if (m_size > embeddedElementCount)
{
memcpy( newData, m_elmArray, minElmCount*sizeof(Element));
}
else if (newSize > embeddedElementCount)
{
memcpy( newData, m_elmData, minElmCount*sizeof(Element));
}
}
void runConstructorsForNewElements(void * newData, unsigned char newSize)
{
Element* newElements = reinterpret_cast<Element*> (newData);
for (int i = m_size; i < newSize; ++i)
{
new (&(newElements[i])) Element;
}
}
void freeOldDataAndUseNew(void * newData, unsigned char newSize)
{
if (m_size > embeddedElementCount)
{
::operator delete (reinterpret_cast<void*>(m_elmArray));
}
if (newSize > embeddedElementCount)
{
m_elmArray = reinterpret_cast<Element*> (newData);
}
m_size = newSize;
}
union {
Element* m_elmArray;
char m_elmData[embeddedElementCount*sizeof(Element)];
};
unsigned char m_size;
};
#pragma pack()
#endif // SMALLVECTOR_H