FVector.hpp 12 KB
Newer Older
1
// ===================================================================================
2
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
3
4
5
6
7
8
9
10
11
12
13
14
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.  
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info". 
// "http://www.gnu.org/licenses".
15
// ===================================================================================
16
17
#ifndef FVECTOR_HPP
#define FVECTOR_HPP
18

19
20
21

#include "../Utils/FGlobal.hpp"

22
#include <cstring>
23
24
25

/**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
26
 * @class FVector
27
28
29
30
31
 * Please read the license
 *
 * This class is a vector container.
 * It is a very basic vector to enable strong performance.
 *
32
 * Please refere to unit test utestVector.cpp to know more.
33
 */
34
template<class ObjectType>
35
36
class FVector {
protected:
37
    static const int DefaultSize = 10;      /**< Default size */
38

39
    ObjectType* array;        /**< memory area*/
40

41
42
    int capacity;             /**< memory capacity, the size of array */
    int index;                /**< index in array, the current position to insert */
43
44

public:
45
    typedef ObjectType ValueType; /**< data type of data in FVector */
messner's avatar
messner committed
46

47
    /**
48
49
    * @brief Constructor
    * Create a vector with a default size capacity
50
    */
51
    FVector() : array(nullptr), capacity(DefaultSize), index(0) {
52
        array = reinterpret_cast< ObjectType* >( new char[sizeof(ObjectType) * DefaultSize] );
53
54
55
    }

    /**
56
57
    * @brief Constructor
    * @param inCapacity the memory to allocate
58
    */
59
    explicit FVector(const int inCapacity): array(nullptr), capacity(inCapacity), index(0) {
60
61
62
        if( inCapacity ){
            array = reinterpret_cast< ObjectType* >( new char[sizeof(ObjectType) * inCapacity]);
        }
63
64
    }

65
66
67
    /**
     * Copy constructor
     * @param other original vector
68
     * object must have an copy constructor
69
     */
70
    FVector(const FVector& other): array(nullptr), capacity(other.capacity), index(other.index) {
71
72
73
74
75
76
        if( other.capacity ){
            array = reinterpret_cast< ObjectType* >( new char[sizeof(ObjectType) * other.capacity]);
            // Copy each element
            for(int idx = 0 ; idx < other.index ; ++idx){
                new((void*)&array[idx]) ObjectType(other.array[idx]);
            }
77
78
79
        }
    }

80
81
82
    /** Copy operator
      * @param other the original vector
      * @return this after copying data
83
84
85
      * Objects of the current vector are deleted then
      * objects from other are copied using copy constructor.
      * The capacity is not copied.
86
      */
87
    FVector& operator=(const FVector& other){
88
89
90
91
        if(&other != this){
            // clear current element
            clear();
            // alloc bigger if needed
92
93
94
95
            if(capacity < other.getSize()){
                delete [] reinterpret_cast< char* >(array);
                capacity = int(other.getSize() * 1.5);
                array = reinterpret_cast< ObjectType* >( new char[sizeof(ObjectType) * capacity]);
96
            }
97

98
            index = other.index;
99
            for(int idx = 0 ; idx < other.index ; ++idx){
100
                new((void*)&array[idx]) ObjectType(other.array[idx]);
101
            }
102
103
104
105
106
107
108
109
110
        }
        return *this;
    }

    /**
    *@brief destructor
    */
    virtual ~FVector(){
        clear();
111
        delete [] reinterpret_cast< char* >(array);
112
113
114
    }

    /**
115
    * @brief Get the buffer capacity
116
117
    * @return the buffer capacity
    * The capacity is the current memory size allocated.
118
119
    */
    int getCapacity() const{
120
        return capacity;
121
122
123
    }

    /**
124
    *@brief Set the buffer capacity
125
    *@param inCapacity to change the capacity
126
    * If capacity given is lower than size elements after capacity are removed
127
    */
128
129
130
131
    void setCapacity(const int inCapacity) {
        if( inCapacity != capacity ){
            while(inCapacity < index){
                (&array[--index])->~ObjectType();
132
133
            }

134
            // Copy elements
135
            ObjectType* const nextArray = reinterpret_cast< ObjectType* >( inCapacity ? new char[sizeof(ObjectType) * inCapacity] : nullptr);
136
            for(int idx = 0 ; idx < index ; ++idx){
137
                new((void*)&nextArray[idx]) ObjectType(std::move(array[idx]));
138
139
140
                (&array[idx])->~ObjectType();
            }
            delete [] reinterpret_cast< char* >(array);
141

142
143
            array    = nextArray;
            capacity = inCapacity;
144
145
146
        }
    }

147
    /** Resize the vector (and change the capacity if needed) */
148
149
    template <typename... Args>
    void resize(const int newSize, Args... args){
150
151
152
153
154
        if(index < newSize){
            if(capacity < newSize){
                setCapacity(int(newSize*1.5));
            }
            while(index != newSize){
155
                new((void*)&array[index]) ObjectType(args...);
156
157
158
159
160
161
162
            }
        }
        else{
            index = newSize;
        }
    }

163
164

    /**
165
166
    * @return Last inserted object
    * This function return the data at the last position
167
    */
168
169
    const ObjectType& head() const {
        return array[index - 1];
170
171
172
    }

    /**
173
174
    * @return Last inserted object
    * This function return the data at the last position
175
    */
176
177
    ObjectType& head() {
        return array[index - 1];
178
179
180
    }

    /**
181
    * @brief Delete all, then size = 0 but capacity is unchanged
182
    */
183
184
185
    void clear() {
        while(0 < index){
            (&array[--index])->~ObjectType();
186
187
188
189
        }
    }

    /**
190
191
    * @return The number of element added into the vector
    * This is not the capcity
192
193
    */
    int getSize() const{
194
        return index;
195
196
197
    }

    /**
198
    * @brief pop the first value
199
    * Warning, FVector do not check that there is an element before poping
200
    * The capacity is unchanged
201
    */
berenger-bramas's avatar
berenger-bramas committed
202
    void pop(){
203
        (&array[--index])->~ObjectType();
204
205
206
    }

    /**
207
208
    * Add a value at the end, resize the capacity if needed
    * @param inValue the new value
209
    */
210
    void push( const ObjectType & inValue ){
211
        // if needed, increase the vector
212
213
        if( index == capacity ){
            setCapacity(int((capacity+1) * 1.5));
214
        }
215
        // add the new element
216
        new((void*)&array[index++]) ObjectType(inValue);
217
218
    }

219
220
221
222
223
224
225
226
227
228
229
230
231
    /**
     * To Create a new object
     */
    template <typename... Args>
    void pushNew(Args... args){
        // if needed, increase the vector
        if( index == capacity ){
            setCapacity(int((capacity+1) * 1.5));
        }
        // add the new element
        new((void*)&array[index++]) ObjectType(args...);
    }

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
    /**
    * Add one value multiple time
    * @param inValue the new value
    * @param inRepeat the number of time the value is inserted
    */
    void set( const ObjectType & inValue, const int inRepeat){
        // if needed, increase the vector
        if( capacity < index + inRepeat ){
            setCapacity(int((index + inRepeat) * 1.5));
        }
        // add the new element
        for( int idx = 0 ; idx < inRepeat ; ++idx){
            new((void*)&array[index++]) ObjectType(inValue);
        }
    }

248
    /**
249
    *@brief Get a reference of a given value
250
251
252
    *@param inPosition the query position
    *@return the value
    */
253
254
    ObjectType& operator[](const int inPosition ) {
            return array[inPosition];
255
256
257
    }

    /**
258
259
260
    * @brief Get a const reference of a given value
    * @param inPosition the query position
    * @return the value
261
    */
262
263
    const ObjectType& operator[](const int inPosition ) const {
            return array[inPosition];
264
265
    }

266
    /** To get the entire array memory
berenger-bramas's avatar
berenger-bramas committed
267
268
      * @return the array allocated by the vector
      */
269
270
    ObjectType* data(){
        return array;
berenger-bramas's avatar
berenger-bramas committed
271
272
    }

273
    /** To get the entire array memory
berenger-bramas's avatar
berenger-bramas committed
274
275
      * @return the array allocated by the vector
      */
276
277
    const ObjectType* data() const{
        return array;
berenger-bramas's avatar
berenger-bramas committed
278
279
    }

280
    /** To take values from C array but copy with = operator
281
      * @param inArray the array to copy values
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
      * @param inSize the size of the array
      */
    void extractValues(const ObjectType*const inArray, const int inSize){
        // Check available memory
        if(capacity < index + inSize){
            setCapacity( int((index + inSize) * 1.5) );
        }
        // Copy values
        for(int idx = 0 ; idx < inSize ; ++idx){
            new((void*)&array[index++]) ObjectType(inArray[idx]);
        }
    }

    /** To take values from C array but copy with memcpy
      * @param inArray the array to copie values
      * @param inSize the size of the array
      */
    void memocopy(const ObjectType*const inArray, const int inSize){
        // Check available memory
        if(capacity < index + inSize){
            setCapacity( int((index + inSize) * 1.5) );
        }
        // Copy values
        memcpy(&array[index], inArray, inSize * sizeof(ObjectType));
        index += inSize;
    }

309
310
311
312
313
314
315
316
    /** Remove a values by shifting all the next values */
    void removeOne(const int idxToRemove){
        for(int idxMove = idxToRemove + 1; idxMove < index ; ++idxMove){
            array[idxMove - 1] = array[idxMove];
        }
        index -= 1;
    }

317
    /** This class is a basic iterator
318
319
320
321
322
323
324
      * <code>
      *  typename FVector<int>::ConstBasicIterator iter(myVector);<br>
      *  while( iter.hasNotFinished() ){<br>
      *      printf("%d\n",iter.data());<br>
      *      iter.gotoNext();<br>
      *  } <br>
      * </code>
325
      */
326
    class BasicIterator {
327
328
329
330
331
    protected:
        FVector* const vector;  /**< the vector to work on*/
        int index;              /**< the current node*/

    public:
332
        /** Empty destructor */
333
334
        virtual ~BasicIterator(){}

335
        /** Constructor need a vector */
336
        explicit BasicIterator(FVector<ObjectType>& inVector) : vector(&inVector), index(0){}
337

338
        /** Go to next vector element */
339
340
        void gotoNext() {
            ++index;
341
342
        }

343
344
345
        /** is it over
          * @return true if we are over the vector
          */
346
347
        bool hasNotFinished() const {
            return index < vector->index;
348
349
        }

350
        /** Get current data */
351
352
        ObjectType& data(){
            return vector->array[index];
353
354
        }

355
        /** Get current data */
356
357
        const ObjectType& data() const{
            return vector->array[index];
358
359
        }

360
        /** Set the data */
361
362
        void setData(const ObjectType& inData){
            vector->array[index] = inData;
363
364
        }

365
366
367
        /** Remove current data
          * It will move all the data after to their previous position
          */
368
369
        void remove(){
            if( hasNotFinished() ){
370
                for(int idxMove = index + 1; idxMove < vector->index ; ++idxMove){
371
372
                    vector->array[idxMove - 1] = vector->array[idxMove];
                }
373
                vector->index -= 1;
374
375
376
            }
        }

377
378
379
    };
    friend class BasicIterator;

380
381
382
    /** This class is a basic const iterator
      * it uses a const vector to work on
      */
383
    class ConstBasicIterator {
384
385
    protected:
        const FVector* const vector;  /**< the vector to work on*/
386
        int index;                    /**< the current node*/
387
388

    public:
389
        /** Empty destructor */
390
391
        virtual ~ConstBasicIterator(){}

392
        /** Constructor need a vector */
393
        explicit ConstBasicIterator(const FVector<ObjectType>& inVector) : vector(&inVector), index(0){}
394

395
        /** Go to next vector element */
berenger-bramas's avatar
berenger-bramas committed
396
        void gotoNext(){
397
            ++index;
398
399
        }

400
401
402
        /** is it over
          * @return true if we are over the vector
          */
berenger-bramas's avatar
berenger-bramas committed
403
        bool hasNotFinished() const{
404
            return index < vector->index;
405
406
        }

407
        /** Get current data */
408
409
        const ObjectType& data() const{
            return vector->array[index];
410
411
412
413
414
415
416
417
418
419
420
        }

    };
    friend class ConstBasicIterator;

};



#endif // FVECTOR_HPP