blob: d55c5b3b99b6f7f6af6966fe0336a6d1bcfc4ad4 [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*
Pau Espin Pedrol21d03d32019-07-22 12:05:52 +02005* SPDX-License-Identifier: AGPL-3.0+
6*
dburgess82c46ff2011-10-07 02:40:51 +00007* This software is distributed under the terms of the GNU Affero Public License.
8* See the COPYING file in the main directory for details.
9*
10* This use of this software may be subject to additional restrictions.
11* See the LEGAL file in the main directory for details.
12
13 This program is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Affero General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Affero General Public License for more details.
22
23 You should have received a copy of the GNU Affero General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26*/
27
28
29
30
31#ifndef VECTOR_H
32#define VECTOR_H
33
34#include <string.h>
35#include <iostream>
36#include <assert.h>
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010037#include <stdlib.h>
38
Martin Hauke066fd042019-10-13 19:08:00 +020039// We can't use Logger.h in this file...
kurtis.heimerl5a872472013-05-31 21:47:25 +000040extern int gVectorDebug;
41#define BVDEBUG(msg) if (gVectorDebug) {std::cout << msg;}
42
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010043typedef void (*vector_free_func)(void* wData);
44typedef void *(*vector_alloc_func)(size_t newSize);
dburgess82c46ff2011-10-07 02:40:51 +000045
46/**
47 A simplified Vector template with aliases.
48 Unlike std::vector, this class does not support dynamic resizing.
49 Unlike std::vector, this class does support "aliases" and subvectors.
50*/
51template <class T> class Vector {
52
53 // TODO -- Replace memcpy calls with for-loops.
54
55 public:
56
57 /**@name Iterator types. */
58 //@{
59 typedef T* iterator;
60 typedef const T* const_iterator;
61 //@}
62
63 protected:
64
65 T* mData; ///< allocated data block, if any
66 T* mStart; ///< start of useful data
67 T* mEnd; ///< end of useful data + 1
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010068 vector_alloc_func mAllocFunc; ///< function used to alloc new mData during resize.
69 vector_free_func mFreeFunc; ///< function used to free mData.
dburgess82c46ff2011-10-07 02:40:51 +000070
71 public:
72
kurtis.heimerl5a872472013-05-31 21:47:25 +000073 /****
74 char *inspect() {
75 static char buf[100];
76 sprintf(buf," mData=%p mStart=%p mEnd=%p ",mData,mStart,mEnd);
77 return buf;
78 }
79 ***/
80
dburgess82c46ff2011-10-07 02:40:51 +000081 /** Return the size of the Vector. */
82 size_t size() const
83 {
84 assert(mStart>=mData);
85 assert(mEnd>=mStart);
86 return mEnd - mStart;
87 }
88
89 /** Return size in bytes. */
90 size_t bytes() const { return size()*sizeof(T); }
91
92 /** Change the size of the Vector, discarding content. */
93 void resize(size_t newSize)
94 {
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010095 if (mData!=NULL) {
96 if (mFreeFunc)
97 mFreeFunc(mData);
98 else
99 delete[] mData;
100 }
dburgess82c46ff2011-10-07 02:40:51 +0000101 if (newSize==0) mData=NULL;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100102 else {
103 if (mAllocFunc)
104 mData = (T*) mAllocFunc(newSize);
105 else
106 mData = new T[newSize];
107 }
dburgess82c46ff2011-10-07 02:40:51 +0000108 mStart = mData;
109 mEnd = mStart + newSize;
110 }
111
Alexander Chemerisf0189c42017-03-18 14:08:43 -0700112 /** Reduce addressable size of the Vector, keeping content. */
113 void shrink(size_t newSize)
114 {
115 assert(newSize <= mEnd - mStart);
116 mEnd = mStart + newSize;
117 }
118
dburgess82c46ff2011-10-07 02:40:51 +0000119 /** Release memory and clear pointers. */
120 void clear() { resize(0); }
121
122
123 /** Copy data from another vector. */
124 void clone(const Vector<T>& other)
125 {
126 resize(other.size());
Pau Espin Pedrol5e68cde2018-08-30 20:45:14 +0200127 other.copyTo(*this);
dburgess82c46ff2011-10-07 02:40:51 +0000128 }
129
130
131
132
133 //@{
134
135 /** Build an empty Vector of a given size. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100136 Vector(size_t wSize=0, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
137 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
138 { resize(wSize); }
dburgess82c46ff2011-10-07 02:40:51 +0000139
Tom Tsou87d158c2017-06-16 10:21:16 -0700140 /** Build a Vector by moving another. */
141 Vector(Vector<T>&& other)
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100142 :mData(other.mData),mStart(other.mStart),mEnd(other.mEnd), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000143 { other.mData=NULL; }
144
145 /** Build a Vector by copying another. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100146 Vector(const Vector<T>& other):mData(NULL), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc) { clone(other); }
dburgess82c46ff2011-10-07 02:40:51 +0000147
148 /** Build a Vector with explicit values. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100149 Vector(T* wData, T* wStart, T* wEnd, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
150 :mData(wData),mStart(wStart),mEnd(wEnd), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000151 { }
152
153 /** Build a vector from an existing block, NOT to be deleted upon destruction. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100154 Vector(T* wStart, size_t span, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
155 :mData(NULL),mStart(wStart),mEnd(wStart+span),mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000156 { }
157
158 /** Build a Vector by concatenation. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100159 Vector(const Vector<T>& other1, const Vector<T>& other2, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
160 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000161 {
162 resize(other1.size()+other2.size());
163 memcpy(mStart, other1.mStart, other1.bytes());
164 memcpy(mStart+other1.size(), other2.mStart, other2.bytes());
165 }
166
167 //@}
168
169 /** Destroy a Vector, deleting held memory. */
170 ~Vector() { clear(); }
171
172
173
174
175 //@{
176
177 /** Assign from another Vector, shifting ownership. */
178 void operator=(Vector<T>& other)
179 {
180 clear();
181 mData=other.mData;
182 mStart=other.mStart;
183 mEnd=other.mEnd;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100184 mAllocFunc=other.mAllocFunc;
185 mFreeFunc=other.mFreeFunc;
dburgess82c46ff2011-10-07 02:40:51 +0000186 other.mData=NULL;
187 }
188
189 /** Assign from another Vector, copying. */
190 void operator=(const Vector<T>& other) { clone(other); }
191
192 //@}
193
194
195 //@{
196
197 /** Return an alias to a segment of this Vector. */
198 Vector<T> segment(size_t start, size_t span)
199 {
200 T* wStart = mStart + start;
201 T* wEnd = wStart + span;
202 assert(wEnd<=mEnd);
203 return Vector<T>(NULL,wStart,wEnd);
204 }
205
206 /** Return an alias to a segment of this Vector. */
207 const Vector<T> segment(size_t start, size_t span) const
208 {
209 T* wStart = mStart + start;
210 T* wEnd = wStart + span;
211 assert(wEnd<=mEnd);
212 return Vector<T>(NULL,wStart,wEnd);
213 }
214
215 Vector<T> head(size_t span) { return segment(0,span); }
216 const Vector<T> head(size_t span) const { return segment(0,span); }
217 Vector<T> tail(size_t start) { return segment(start,size()-start); }
218 const Vector<T> tail(size_t start) const { return segment(start,size()-start); }
219
220 /**
221 Copy part of this Vector to a segment of another Vector.
222 @param other The other vector.
223 @param start The start point in the other vector.
224 @param span The number of elements to copy.
225 */
226 void copyToSegment(Vector<T>& other, size_t start, size_t span) const
227 {
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200228 unsigned int i;
229 T* dst = other.mStart + start;
230 T* src = mStart;
231 assert(dst+span<=other.mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000232 assert(mStart+span<=mEnd);
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200233 for (i = 0; i < span; i++, src++, dst++)
234 *dst = *src;
Pau Espin Pedrol93707d02020-02-25 17:02:53 +0100235 /*TODO if not non-trivially copiable type class, optimize:
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200236 memcpy(dst,mStart,span*sizeof(T)); */
dburgess82c46ff2011-10-07 02:40:51 +0000237 }
238
239 /** Copy all of this Vector to a segment of another Vector. */
240 void copyToSegment(Vector<T>& other, size_t start=0) const { copyToSegment(other,start,size()); }
241
242 void copyTo(Vector<T>& other) const { copyToSegment(other,0,size()); }
243
244 /**
245 Copy a segment of this vector into another.
246 @param other The other vector (to copt into starting at 0.)
247 @param start The start point in this vector.
248 @param span The number of elements to copy.
249 */
250 void segmentCopyTo(Vector<T>& other, size_t start, size_t span) const
251 {
252 const T* base = mStart + start;
253 assert(base+span<=mEnd);
254 assert(other.mStart+span<=other.mEnd);
255 memcpy(other.mStart,base,span*sizeof(T));
256 }
257
Alexander Chemerisc7088162017-03-18 13:43:22 -0700258 /**
259 Move (copy) a segment of this vector into a different position in the vector
260 @param from Start point from which to copy.
261 @param to Start point to which to copy.
262 @param span The number of elements to copy.
263 */
264 void segmentMove(size_t from, size_t to, size_t span)
265 {
266 const T* baseFrom = mStart + from;
267 T* baseTo = mStart + to;
268 assert(baseFrom+span<=mEnd);
269 assert(baseTo+span<=mEnd);
270 memmove(baseTo,baseFrom,span*sizeof(T));
271 }
272
dburgess82c46ff2011-10-07 02:40:51 +0000273 void fill(const T& val)
274 {
275 T* dp=mStart;
276 while (dp<mEnd) *dp++=val;
277 }
278
279 void fill(const T& val, unsigned start, unsigned length)
280 {
281 T* dp=mStart+start;
282 T* end=dp+length;
283 assert(end<=mEnd);
284 while (dp<end) *dp++=val;
285 }
286
287
288 //@}
289
290
291 //@{
292
293 T& operator[](size_t index)
294 {
295 assert(mStart+index<mEnd);
296 return mStart[index];
297 }
298
299 const T& operator[](size_t index) const
300 {
301 assert(mStart+index<mEnd);
302 return mStart[index];
303 }
304
305 const T* begin() const { return mStart; }
306 T* begin() { return mStart; }
307 const T* end() const { return mEnd; }
308 T* end() { return mEnd; }
kurtis.heimerl5a872472013-05-31 21:47:25 +0000309 bool isOwner() { return !!mData; } // Do we own any memory ourselves?
dburgess82c46ff2011-10-07 02:40:51 +0000310 //@}
Pau Espin Pedrol21ce05c2018-08-30 20:47:20 +0200311
dburgess82c46ff2011-10-07 02:40:51 +0000312
313};
314
315
316
317
318/** Basic print operator for Vector objects. */
319template <class T>
320std::ostream& operator<<(std::ostream& os, const Vector<T>& v)
321{
322 for (unsigned i=0; i<v.size(); i++) os << v[i] << " ";
323 return os;
324}
325
326
327
328#endif
329// vim: ts=4 sw=4