-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSmartVector.cpp
143 lines (116 loc) · 3.49 KB
/
SmartVector.cpp
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
135
136
137
138
139
140
141
#include<vector>
#include<variant>
#include<array>
#include<cstdint>
#include<iostream>
#include<cassert>
// a mimimal smart vector that can be either an array or a vector
template<typename T>
class SmartVector {
public :
using Vector = std::vector<T>;
static constexpr uint32_t maxSize = sizeof(Vector)/sizeof(T)-1;
using Array = std::array<T,sizeof(Vector)/sizeof(T)>;
using Variant = std::variant<Vector,Array>;
SmartVector(){}
template<typename Iter>
SmartVector(Iter b, Iter e) {
initialize(b,e);
}
template<typename Iter>
void initialize(Iter b, Iter e) {
if (e-b<=maxSize) {
m_container = Array();
auto & a = std::get<Array>(m_container);
std::copy(b,e,a.begin());
a.back()=e-b;
} else
m_container. template emplace<Vector>(b,e);
}
template<typename Iter>
void extend(Iter b, Iter e) {
if(auto pval = std::get_if<Array>(&m_container)) {
auto cs = pval->back();
uint32_t ns = (e-b)+cs;
if (ns<=maxSize) {
std::copy(b,e,&(*pval)[cs]);
pval->back()=ns;
} else {
Vector v; v.reserve(ns);
v.insert(v.end(),pval->begin(),pval->begin()+cs);
v.insert(v.end(),b,e);
m_container = std::move(v);
}
}else if(auto pval = std::get_if<Vector>(&m_container)) {
pval->insert(pval->end(),b,e);
}
else {
initialize(b,e);
}
}
T const * begin() const {
if(auto pval = std::get_if<Array>(&m_container))
return pval->data();
else
return std::get<Vector>(m_container).data();
}
T const * end() const {
if(auto pval = std::get_if<Array>(&m_container))
return pval->data()+pval->back();
else
return std::get<Vector>(m_container).data()+std::get<Vector>(m_container).size();
}
T const & operator[](uint32_t i) const {
return *(begin()+i);
}
uint32_t size() const {
if(auto pval = std::get_if<Array>(&m_container))
return pval->back();
else
return std::get<Vector>(m_container).size();
}
Variant const & container() const { return m_container;}
private:
Variant m_container;
};
int main() {
using Vector = std::vector<uint8_t>;
using Array = std::array<uint8_t,sizeof(Vector)/sizeof(uint8_t)>;
using Variant = SmartVector<uint8_t>;
std::cout << sizeof(Vector) <<' '<< sizeof(Array) <<' '<< sizeof(Variant) << std::endl;
Variant v;
uint8_t data[128];
for (int i=0; i<128; ++i) data[i]=i;
uint8_t i=0;
Variant va(data,data+5);
assert(5==va.size());
assert(5==va.end()-va.begin());
assert(std::get_if<Array>(&va.container()));
i=0; for (auto c : va) assert(c==i++);
Variant vb; vb.initialize(data,data+24);
assert(24==vb.size());
assert(24==vb.end()-vb.begin());
assert(std::get_if<Vector>(&vb.container()));
i=0; for (auto c : vb) assert(c==i++);
Variant vv; vv.extend(data,data+64);
assert(64==vv.size());
assert(64==vv.end()-vv.begin());
assert(std::get_if<Vector>(&vv.container()));
i=0; for (auto c : vv) assert(c==i++);
va.extend(data+5,data+10);
assert(10==va.size());
assert(10==va.end()-va.begin());
assert(std::get_if<Array>(&va.container()));
i=0; for (auto c : va) assert(c==i++);
va.extend(data+10,data+64);
assert(64==va.size());
assert(64==va.end()-va.begin());
assert(std::get_if<Vector>(&va.container()));
i=0; for (auto c : va) assert(c==i++);
vv.extend(data+64,data+72);
assert(72==vv.size());
assert(72==vv.end()-vv.begin());
assert(std::get_if<Vector>(&vv.container()));
i=0; for (auto c : vv) assert(c==i++);
return 0;
}