blob: 4c96b7873af1b6d46db49c15808fe67a18b7bca3 [file] [log] [blame]
dburgess82c46ff2011-10-07 02:40:51 +00001/**@file Simplified Vector template with aliases. */
2/*
3* Copyright 2008 Free Software Foundation, Inc.
4*
5* This software is distributed under the terms of the GNU Affero Public License.
6* See the COPYING file in the main directory for details.
7*
8* This use of this software may be subject to additional restrictions.
9* See the LEGAL file in the main directory for details.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU Affero General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Affero General Public License for more details.
20
21 You should have received a copy of the GNU Affero General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24*/
25
26
27
28
29#ifndef VECTOR_H
30#define VECTOR_H
31
32#include <string.h>
33#include <iostream>
34#include <assert.h>
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010035#include <stdlib.h>
36
kurtis.heimerl5a872472013-05-31 21:47:25 +000037// We cant use Logger.h in this file...
38extern int gVectorDebug;
39#define BVDEBUG(msg) if (gVectorDebug) {std::cout << msg;}
40
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010041typedef void (*vector_free_func)(void* wData);
42typedef void *(*vector_alloc_func)(size_t newSize);
dburgess82c46ff2011-10-07 02:40:51 +000043
44/**
45 A simplified Vector template with aliases.
46 Unlike std::vector, this class does not support dynamic resizing.
47 Unlike std::vector, this class does support "aliases" and subvectors.
48*/
49template <class T> class Vector {
50
51 // TODO -- Replace memcpy calls with for-loops.
52
53 public:
54
55 /**@name Iterator types. */
56 //@{
57 typedef T* iterator;
58 typedef const T* const_iterator;
59 //@}
60
61 protected:
62
63 T* mData; ///< allocated data block, if any
64 T* mStart; ///< start of useful data
65 T* mEnd; ///< end of useful data + 1
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010066 vector_alloc_func mAllocFunc; ///< function used to alloc new mData during resize.
67 vector_free_func mFreeFunc; ///< function used to free mData.
dburgess82c46ff2011-10-07 02:40:51 +000068
69 public:
70
kurtis.heimerl5a872472013-05-31 21:47:25 +000071 /****
72 char *inspect() {
73 static char buf[100];
74 sprintf(buf," mData=%p mStart=%p mEnd=%p ",mData,mStart,mEnd);
75 return buf;
76 }
77 ***/
78
dburgess82c46ff2011-10-07 02:40:51 +000079 /** Return the size of the Vector. */
80 size_t size() const
81 {
82 assert(mStart>=mData);
83 assert(mEnd>=mStart);
84 return mEnd - mStart;
85 }
86
87 /** Return size in bytes. */
88 size_t bytes() const { return size()*sizeof(T); }
89
90 /** Change the size of the Vector, discarding content. */
91 void resize(size_t newSize)
92 {
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010093 if (mData!=NULL) {
94 if (mFreeFunc)
95 mFreeFunc(mData);
96 else
97 delete[] mData;
98 }
dburgess82c46ff2011-10-07 02:40:51 +000099 if (newSize==0) mData=NULL;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100100 else {
101 if (mAllocFunc)
102 mData = (T*) mAllocFunc(newSize);
103 else
104 mData = new T[newSize];
105 }
dburgess82c46ff2011-10-07 02:40:51 +0000106 mStart = mData;
107 mEnd = mStart + newSize;
108 }
109
Alexander Chemerisf0189c42017-03-18 14:08:43 -0700110 /** Reduce addressable size of the Vector, keeping content. */
111 void shrink(size_t newSize)
112 {
113 assert(newSize <= mEnd - mStart);
114 mEnd = mStart + newSize;
115 }
116
dburgess82c46ff2011-10-07 02:40:51 +0000117 /** Release memory and clear pointers. */
118 void clear() { resize(0); }
119
120
121 /** Copy data from another vector. */
122 void clone(const Vector<T>& other)
123 {
124 resize(other.size());
Pau Espin Pedrol5e68cde2018-08-30 20:45:14 +0200125 other.copyTo(*this);
dburgess82c46ff2011-10-07 02:40:51 +0000126 }
127
128
129
130
131 //@{
132
133 /** Build an empty Vector of a given size. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100134 Vector(size_t wSize=0, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
135 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
136 { resize(wSize); }
dburgess82c46ff2011-10-07 02:40:51 +0000137
Tom Tsou87d158c2017-06-16 10:21:16 -0700138 /** Build a Vector by moving another. */
139 Vector(Vector<T>&& other)
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100140 :mData(other.mData),mStart(other.mStart),mEnd(other.mEnd), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000141 { other.mData=NULL; }
142
143 /** Build a Vector by copying another. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100144 Vector(const Vector<T>& other):mData(NULL), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc) { clone(other); }
dburgess82c46ff2011-10-07 02:40:51 +0000145
146 /** Build a Vector with explicit values. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100147 Vector(T* wData, T* wStart, T* wEnd, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
148 :mData(wData),mStart(wStart),mEnd(wEnd), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000149 { }
150
151 /** Build a vector from an existing block, NOT to be deleted upon destruction. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100152 Vector(T* wStart, size_t span, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
153 :mData(NULL),mStart(wStart),mEnd(wStart+span),mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000154 { }
155
156 /** Build a Vector by concatenation. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100157 Vector(const Vector<T>& other1, const Vector<T>& other2, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
158 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000159 {
160 resize(other1.size()+other2.size());
161 memcpy(mStart, other1.mStart, other1.bytes());
162 memcpy(mStart+other1.size(), other2.mStart, other2.bytes());
163 }
164
165 //@}
166
167 /** Destroy a Vector, deleting held memory. */
168 ~Vector() { clear(); }
169
170
171
172
173 //@{
174
175 /** Assign from another Vector, shifting ownership. */
176 void operator=(Vector<T>& other)
177 {
178 clear();
179 mData=other.mData;
180 mStart=other.mStart;
181 mEnd=other.mEnd;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100182 mAllocFunc=other.mAllocFunc;
183 mFreeFunc=other.mFreeFunc;
dburgess82c46ff2011-10-07 02:40:51 +0000184 other.mData=NULL;
185 }
186
187 /** Assign from another Vector, copying. */
188 void operator=(const Vector<T>& other) { clone(other); }
189
190 //@}
191
192
193 //@{
194
195 /** Return an alias to a segment of this Vector. */
196 Vector<T> segment(size_t start, size_t span)
197 {
198 T* wStart = mStart + start;
199 T* wEnd = wStart + span;
200 assert(wEnd<=mEnd);
201 return Vector<T>(NULL,wStart,wEnd);
202 }
203
204 /** Return an alias to a segment of this Vector. */
205 const Vector<T> segment(size_t start, size_t span) const
206 {
207 T* wStart = mStart + start;
208 T* wEnd = wStart + span;
209 assert(wEnd<=mEnd);
210 return Vector<T>(NULL,wStart,wEnd);
211 }
212
213 Vector<T> head(size_t span) { return segment(0,span); }
214 const Vector<T> head(size_t span) const { return segment(0,span); }
215 Vector<T> tail(size_t start) { return segment(start,size()-start); }
216 const Vector<T> tail(size_t start) const { return segment(start,size()-start); }
217
218 /**
219 Copy part of this Vector to a segment of another Vector.
220 @param other The other vector.
221 @param start The start point in the other vector.
222 @param span The number of elements to copy.
223 */
224 void copyToSegment(Vector<T>& other, size_t start, size_t span) const
225 {
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200226 unsigned int i;
227 T* dst = other.mStart + start;
228 T* src = mStart;
229 assert(dst+span<=other.mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000230 assert(mStart+span<=mEnd);
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200231 for (i = 0; i < span; i++, src++, dst++)
232 *dst = *src;
233 /*TODO if not non-trivially copyable type class, optimize:
234 memcpy(dst,mStart,span*sizeof(T)); */
dburgess82c46ff2011-10-07 02:40:51 +0000235 }
236
237 /** Copy all of this Vector to a segment of another Vector. */
238 void copyToSegment(Vector<T>& other, size_t start=0) const { copyToSegment(other,start,size()); }
239
240 void copyTo(Vector<T>& other) const { copyToSegment(other,0,size()); }
241
242 /**
243 Copy a segment of this vector into another.
244 @param other The other vector (to copt into starting at 0.)
245 @param start The start point in this vector.
246 @param span The number of elements to copy.
247 */
248 void segmentCopyTo(Vector<T>& other, size_t start, size_t span) const
249 {
250 const T* base = mStart + start;
251 assert(base+span<=mEnd);
252 assert(other.mStart+span<=other.mEnd);
253 memcpy(other.mStart,base,span*sizeof(T));
254 }
255
Alexander Chemerisc7088162017-03-18 13:43:22 -0700256 /**
257 Move (copy) a segment of this vector into a different position in the vector
258 @param from Start point from which to copy.
259 @param to Start point to which to copy.
260 @param span The number of elements to copy.
261 */
262 void segmentMove(size_t from, size_t to, size_t span)
263 {
264 const T* baseFrom = mStart + from;
265 T* baseTo = mStart + to;
266 assert(baseFrom+span<=mEnd);
267 assert(baseTo+span<=mEnd);
268 memmove(baseTo,baseFrom,span*sizeof(T));
269 }
270
dburgess82c46ff2011-10-07 02:40:51 +0000271 void fill(const T& val)
272 {
273 T* dp=mStart;
274 while (dp<mEnd) *dp++=val;
275 }
276
277 void fill(const T& val, unsigned start, unsigned length)
278 {
279 T* dp=mStart+start;
280 T* end=dp+length;
281 assert(end<=mEnd);
282 while (dp<end) *dp++=val;
283 }
284
285
286 //@}
287
288
289 //@{
290
291 T& operator[](size_t index)
292 {
293 assert(mStart+index<mEnd);
294 return mStart[index];
295 }
296
297 const T& operator[](size_t index) const
298 {
299 assert(mStart+index<mEnd);
300 return mStart[index];
301 }
302
303 const T* begin() const { return mStart; }
304 T* begin() { return mStart; }
305 const T* end() const { return mEnd; }
306 T* end() { return mEnd; }
kurtis.heimerl5a872472013-05-31 21:47:25 +0000307 bool isOwner() { return !!mData; } // Do we own any memory ourselves?
dburgess82c46ff2011-10-07 02:40:51 +0000308 //@}
Pau Espin Pedrol21ce05c2018-08-30 20:47:20 +0200309
dburgess82c46ff2011-10-07 02:40:51 +0000310
311};
312
313
314
315
316/** Basic print operator for Vector objects. */
317template <class T>
318std::ostream& operator<<(std::ostream& os, const Vector<T>& v)
319{
320 for (unsigned i=0; i<v.size(); i++) os << v[i] << " ";
321 return os;
322}
323
324
325
326#endif
327// vim: ts=4 sw=4