blob: 6d1045d189fe40984a544f89096bdc5d429040fa [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
Eric7a52e422020-08-14 03:11:22 +020039#ifndef __OPTIMIZE__
40#define assert_no_opt(x) assert(x)
41#else
42#define assert_no_opt(x)
43#endif
Martin Hauke066fd042019-10-13 19:08:00 +020044// We can't use Logger.h in this file...
kurtis.heimerl5a872472013-05-31 21:47:25 +000045extern int gVectorDebug;
46#define BVDEBUG(msg) if (gVectorDebug) {std::cout << msg;}
47
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010048typedef void (*vector_free_func)(void* wData);
49typedef void *(*vector_alloc_func)(size_t newSize);
dburgess82c46ff2011-10-07 02:40:51 +000050
51/**
52 A simplified Vector template with aliases.
53 Unlike std::vector, this class does not support dynamic resizing.
54 Unlike std::vector, this class does support "aliases" and subvectors.
55*/
56template <class T> class Vector {
57
58 // TODO -- Replace memcpy calls with for-loops.
59
60 public:
61
62 /**@name Iterator types. */
63 //@{
64 typedef T* iterator;
65 typedef const T* const_iterator;
66 //@}
67
68 protected:
69
70 T* mData; ///< allocated data block, if any
71 T* mStart; ///< start of useful data
72 T* mEnd; ///< end of useful data + 1
Pau Espin Pedrolf7331762018-12-03 17:46:04 +010073 vector_alloc_func mAllocFunc; ///< function used to alloc new mData during resize.
74 vector_free_func mFreeFunc; ///< function used to free mData.
dburgess82c46ff2011-10-07 02:40:51 +000075
76 public:
77
kurtis.heimerl5a872472013-05-31 21:47:25 +000078 /****
79 char *inspect() {
80 static char buf[100];
81 sprintf(buf," mData=%p mStart=%p mEnd=%p ",mData,mStart,mEnd);
82 return buf;
83 }
84 ***/
85
dburgess82c46ff2011-10-07 02:40:51 +000086 /** Return the size of the Vector. */
87 size_t size() const
88 {
Eric7a52e422020-08-14 03:11:22 +020089 assert_no_opt(mStart>=mData);
90 assert_no_opt(mEnd>=mStart);
dburgess82c46ff2011-10-07 02:40:51 +000091 return mEnd - mStart;
92 }
93
94 /** Return size in bytes. */
95 size_t bytes() const { return size()*sizeof(T); }
96
97 /** Change the size of the Vector, discarding content. */
98 void resize(size_t newSize)
99 {
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100100 if (mData!=NULL) {
101 if (mFreeFunc)
102 mFreeFunc(mData);
103 else
104 delete[] mData;
105 }
dburgess82c46ff2011-10-07 02:40:51 +0000106 if (newSize==0) mData=NULL;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100107 else {
108 if (mAllocFunc)
109 mData = (T*) mAllocFunc(newSize);
110 else
111 mData = new T[newSize];
112 }
dburgess82c46ff2011-10-07 02:40:51 +0000113 mStart = mData;
114 mEnd = mStart + newSize;
115 }
116
Alexander Chemerisf0189c42017-03-18 14:08:43 -0700117 /** Reduce addressable size of the Vector, keeping content. */
118 void shrink(size_t newSize)
119 {
Eric7a52e422020-08-14 03:11:22 +0200120 assert_no_opt(newSize <= mEnd - mStart);
Alexander Chemerisf0189c42017-03-18 14:08:43 -0700121 mEnd = mStart + newSize;
122 }
123
dburgess82c46ff2011-10-07 02:40:51 +0000124 /** Release memory and clear pointers. */
125 void clear() { resize(0); }
126
127
128 /** Copy data from another vector. */
129 void clone(const Vector<T>& other)
130 {
131 resize(other.size());
Pau Espin Pedrol5e68cde2018-08-30 20:45:14 +0200132 other.copyTo(*this);
dburgess82c46ff2011-10-07 02:40:51 +0000133 }
134
135
136
137
138 //@{
139
140 /** Build an empty Vector of a given size. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100141 Vector(size_t wSize=0, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
142 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
143 { resize(wSize); }
dburgess82c46ff2011-10-07 02:40:51 +0000144
Tom Tsou87d158c2017-06-16 10:21:16 -0700145 /** Build a Vector by moving another. */
146 Vector(Vector<T>&& other)
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100147 :mData(other.mData),mStart(other.mStart),mEnd(other.mEnd), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000148 { other.mData=NULL; }
149
150 /** Build a Vector by copying another. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100151 Vector(const Vector<T>& other):mData(NULL), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc) { clone(other); }
dburgess82c46ff2011-10-07 02:40:51 +0000152
153 /** Build a Vector with explicit values. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100154 Vector(T* wData, T* wStart, T* wEnd, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
155 :mData(wData),mStart(wStart),mEnd(wEnd), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000156 { }
157
158 /** Build a vector from an existing block, NOT to be deleted upon destruction. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100159 Vector(T* wStart, size_t span, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
160 :mData(NULL),mStart(wStart),mEnd(wStart+span),mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000161 { }
162
163 /** Build a Vector by concatenation. */
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100164 Vector(const Vector<T>& other1, const Vector<T>& other2, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
165 :mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
dburgess82c46ff2011-10-07 02:40:51 +0000166 {
167 resize(other1.size()+other2.size());
168 memcpy(mStart, other1.mStart, other1.bytes());
169 memcpy(mStart+other1.size(), other2.mStart, other2.bytes());
170 }
171
172 //@}
173
174 /** Destroy a Vector, deleting held memory. */
175 ~Vector() { clear(); }
176
177
178
179
180 //@{
181
182 /** Assign from another Vector, shifting ownership. */
183 void operator=(Vector<T>& other)
184 {
185 clear();
186 mData=other.mData;
187 mStart=other.mStart;
188 mEnd=other.mEnd;
Pau Espin Pedrolf7331762018-12-03 17:46:04 +0100189 mAllocFunc=other.mAllocFunc;
190 mFreeFunc=other.mFreeFunc;
dburgess82c46ff2011-10-07 02:40:51 +0000191 other.mData=NULL;
192 }
193
194 /** Assign from another Vector, copying. */
195 void operator=(const Vector<T>& other) { clone(other); }
196
197 //@}
198
199
200 //@{
201
202 /** Return an alias to a segment of this Vector. */
203 Vector<T> segment(size_t start, size_t span)
204 {
205 T* wStart = mStart + start;
206 T* wEnd = wStart + span;
Eric7a52e422020-08-14 03:11:22 +0200207 assert_no_opt(wEnd<=mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000208 return Vector<T>(NULL,wStart,wEnd);
209 }
210
211 /** Return an alias to a segment of this Vector. */
212 const Vector<T> segment(size_t start, size_t span) const
213 {
214 T* wStart = mStart + start;
215 T* wEnd = wStart + span;
Eric7a52e422020-08-14 03:11:22 +0200216 assert_no_opt(wEnd<=mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000217 return Vector<T>(NULL,wStart,wEnd);
218 }
219
220 Vector<T> head(size_t span) { return segment(0,span); }
221 const Vector<T> head(size_t span) const { return segment(0,span); }
222 Vector<T> tail(size_t start) { return segment(start,size()-start); }
223 const Vector<T> tail(size_t start) const { return segment(start,size()-start); }
224
225 /**
226 Copy part of this Vector to a segment of another Vector.
227 @param other The other vector.
228 @param start The start point in the other vector.
229 @param span The number of elements to copy.
230 */
231 void copyToSegment(Vector<T>& other, size_t start, size_t span) const
232 {
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200233 unsigned int i;
234 T* dst = other.mStart + start;
235 T* src = mStart;
Eric7a52e422020-08-14 03:11:22 +0200236 assert_no_opt(dst+span<=other.mEnd);
237 assert_no_opt(mStart+span<=mEnd);
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200238 for (i = 0; i < span; i++, src++, dst++)
239 *dst = *src;
Pau Espin Pedrol93707d02020-02-25 17:02:53 +0100240 /*TODO if not non-trivially copiable type class, optimize:
Pau Espin Pedrole6255532018-08-30 20:55:08 +0200241 memcpy(dst,mStart,span*sizeof(T)); */
dburgess82c46ff2011-10-07 02:40:51 +0000242 }
243
244 /** Copy all of this Vector to a segment of another Vector. */
245 void copyToSegment(Vector<T>& other, size_t start=0) const { copyToSegment(other,start,size()); }
246
247 void copyTo(Vector<T>& other) const { copyToSegment(other,0,size()); }
248
249 /**
250 Copy a segment of this vector into another.
251 @param other The other vector (to copt into starting at 0.)
252 @param start The start point in this vector.
253 @param span The number of elements to copy.
254 */
255 void segmentCopyTo(Vector<T>& other, size_t start, size_t span) const
256 {
257 const T* base = mStart + start;
Eric7a52e422020-08-14 03:11:22 +0200258 assert_no_opt(base+span<=mEnd);
259 assert_no_opt(other.mStart+span<=other.mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000260 memcpy(other.mStart,base,span*sizeof(T));
261 }
262
Alexander Chemerisc7088162017-03-18 13:43:22 -0700263 /**
264 Move (copy) a segment of this vector into a different position in the vector
265 @param from Start point from which to copy.
266 @param to Start point to which to copy.
267 @param span The number of elements to copy.
268 */
269 void segmentMove(size_t from, size_t to, size_t span)
270 {
271 const T* baseFrom = mStart + from;
272 T* baseTo = mStart + to;
Eric7a52e422020-08-14 03:11:22 +0200273 assert_no_opt(baseFrom+span<=mEnd);
274 assert_no_opt(baseTo+span<=mEnd);
Alexander Chemerisc7088162017-03-18 13:43:22 -0700275 memmove(baseTo,baseFrom,span*sizeof(T));
276 }
277
dburgess82c46ff2011-10-07 02:40:51 +0000278 void fill(const T& val)
279 {
280 T* dp=mStart;
281 while (dp<mEnd) *dp++=val;
282 }
283
284 void fill(const T& val, unsigned start, unsigned length)
285 {
286 T* dp=mStart+start;
287 T* end=dp+length;
Eric7a52e422020-08-14 03:11:22 +0200288 assert_no_opt(end<=mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000289 while (dp<end) *dp++=val;
290 }
291
292
293 //@}
294
295
296 //@{
297
298 T& operator[](size_t index)
299 {
Eric7a52e422020-08-14 03:11:22 +0200300 assert_no_opt(mStart+index<mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000301 return mStart[index];
302 }
303
304 const T& operator[](size_t index) const
305 {
Eric7a52e422020-08-14 03:11:22 +0200306 assert_no_opt(mStart+index<mEnd);
dburgess82c46ff2011-10-07 02:40:51 +0000307 return mStart[index];
308 }
309
310 const T* begin() const { return mStart; }
311 T* begin() { return mStart; }
312 const T* end() const { return mEnd; }
313 T* end() { return mEnd; }
kurtis.heimerl5a872472013-05-31 21:47:25 +0000314 bool isOwner() { return !!mData; } // Do we own any memory ourselves?
dburgess82c46ff2011-10-07 02:40:51 +0000315 //@}
Pau Espin Pedrol21ce05c2018-08-30 20:47:20 +0200316
dburgess82c46ff2011-10-07 02:40:51 +0000317
318};
319
320
321
322
323/** Basic print operator for Vector objects. */
324template <class T>
325std::ostream& operator<<(std::ostream& os, const Vector<T>& v)
326{
327 for (unsigned i=0; i<v.size(); i++) os << v[i] << " ";
328 return os;
329}
330
331
332
333#endif
334// vim: ts=4 sw=4