Vector.h
5.53 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//*********************************************************************************
// Lightweight Arduino Compatible implementation of key STL Vector methods
//*********************************************************************************
//
// Zac Staples
// zacstaples (at) mac (dot) com
//
// 13 June 2014...Friday the 13th...therfore this is probably broken
//
// I needed a data structure to hold refernces and/or pointers as a data
// member of an abstract class for sensors on my robot. That's the point
// I decided I wanted the basic implementation of the STL vector available
// to me in my Arduino sketches. This is not a complete implementation of
// the STL vector, but is designed to be "good enough" to take sketches
// further into OOP.
//
// Based on Stroustrup's basic implementation of vector in Programming 3rd
// edition page 656 and his Simple allocator from The c++ programming
// language, 4th edition. However, I needed info from the following sources
// to implement to allocator to correctly handle placement new in
// the AVR/Arduino environment.
//
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
// http://www.glenmccl.com/nd_cmp.htm
// http://www.sourcetricks.com/2008/05/c-placement-new.html#.U5yJF41dW0Q
// http://stackoverflow.com/questions/9805829/arduino-c-destructor
// http://arduino.land/FAQ/index.php?solution_id=1023
//
// Released on the beer license...if this works for you...then remember my
// name an buy me a beer sometime.
// This library is changed and otimized by Joao Lopes F
#ifndef VECTOR_H
#define VECTOR_H
#include <Arduino.h>
//* Begin change by JoaoLopesF
//#define INT int
#define INT uint8_t
// Replace all i++ to i++
//* End change by JoaoLopes
//as far as I can tell placement new is not included with AVR or arduino.h
template<typename T>
void* operator new(size_t s, T* v){
return v;
}
//*********************************************************************************
// Allocator for Vector
//*********************************************************************************
template<typename T> struct Simple_alloc {
Simple_alloc() {};
//memory allocation
T* allocate(INT n)
{ return reinterpret_cast<T*>(new char[n*sizeof(T)]); }
void deallocate(T* p, INT n)
{ delete[] reinterpret_cast<char*>(p); }
//construction/destruction
void construct(T* p, const T& t) { new(p) T(t); }
void destroy(T* p) { p->~T(); }
};
//*********************************************************************************
// Vector
//*********************************************************************************
template<class T, class A = Simple_alloc<T> >
class Vector {
A alloc;
INT sz;
T* elem;
INT space;
Vector(const Vector&); //private copy constrution because I
//have not got this working yet and don't
//want to expose this for clients who might
//be expecting it.
public:
Vector() : sz(0), elem(0), space(0) {}
Vector(const INT s) : sz(0) {
reserve(s);
}
Vector& operator=(const Vector&); //copy assignment
~Vector() {
//* Begin change by JoaoLopesF
//for(INT i=0; i<sz; i++) alloc.destroy(&elem[i]);
clear();
//* End change by JoaoLopes
}
T& operator[](INT n) { return elem[n]; }
const T& operator[](INT n) const { return elem[n]; }
INT size() const { return sz; }
INT capacity() const { return space; }
void reserve(INT newalloc);
void push_back(const T& val);
//* Begin change by JoaoLopesF
void erase(INT index);
void clear();
//* End change by JoaoLopes
};
template<class T, class A>
Vector<T, A>& Vector<T, A>::operator=(const Vector& a) {
if(this==&a) return *this;
if(a.size()<=space) { //enough space, no need for new allocation
for(INT i=0; i<a.size(); i++)
elem[i]=a[i];
sz = a.size();
return *this;
}
T* p = alloc.allocate(a.size()); //get new memory
for(INT i=0; i<a.size(); i++)
alloc.construct(&p[i], a[i]); //copy
for(INT i=0; i<sz; i++)
alloc.destroy(&elem[i]);
space = sz = a.size();
elem = p;
return *this;
}
template<class T, class A> void Vector<T, A>::reserve(INT newalloc){
if(newalloc <= space) return; //never decrease space
T* p = alloc.allocate(newalloc);
for(INT i=0; i<sz; i++)
alloc.construct(&p[i], elem[i]); //copy
for(INT i=0; i<sz; i++)
alloc.destroy(&elem[i]);
alloc.deallocate(elem, space);
elem = p;
space = newalloc;
}
template<class T, class A>
void Vector<T, A>::push_back(const T& val){
//* Begin change by JoaoLopesF
// if(space == 0) reserve(4); //start small
// else if(sz==space) reserve(2*space);
if(space == 0) reserve(2); //Just alloc more few items
else if(sz==space) reserve(space + 2);
//* End change by JoaoLopes
alloc.construct(&elem[sz], val);
++sz;
}
//* Begin change by JoaoLopesF
template<class T, class A> void Vector<T, A>::erase(INT index){ // Erase one item
if(index >= sz) return;
INT newalloc = sz - 1;
T* p = alloc.allocate(newalloc);
INT add = 0;
for(INT i=0; i<sz; i++)
if (i != index) // Not for item to be erased
alloc.construct(&p[add++], elem[i]); //copy
for(INT i=0; i<sz; i++)
alloc.destroy(&elem[i]);
alloc.deallocate(elem, space);
elem = p;
space = newalloc;
sz = newalloc;
}
template<class T, class A> void Vector<T, A>::clear(){ // Clear all
for(INT i=0; i<sz; i++)
alloc.destroy(&elem[i]);
if (space > 0) {
// Serial.print("*** clear: size= ");
// Serial.print(sz);
// Serial.print(" space=");
// Serial.println(space);
alloc.deallocate(elem, space);
}
sz=0;
space=0;
elem=0;
}
//* End change by JoaoLopes
#endif