File: SimpleVector.h

package info (click to toggle)
between 6%2Bdfsg1-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, jessie, jessie-kfreebsd, stretch
  • size: 3,532 kB
  • sloc: cpp: 28,110; php: 718; ansic: 638; objc: 245; sh: 236; makefile: 99; perl: 67
file content (464 lines) | stat: -rw-r--r-- 11,793 bytes parent folder | download | duplicates (10)
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
// Jason Rohrer
// SimpleVector.h

/**
*
*	Simple vector template class. Supports pushing at end and random-access deletions.
*	Dynamically sized.
*
*
*	Created 10-24-99
*	Mods:
*		Jason Rohrer	12-11-99	Added deleteAll function
*		Jason Rohrer	1-30-2000	Changed to return NULL if get called on non-existent element
*		Jason Rohrer	12-20-2000	Added a function for deleting a particular
*									element.
*		Jason Rohrer	12-14-2001	Added a function for getting the index of
*									a particular element.
*		Jason Rohrer	1-24-2003	Added a functions for getting an array or
*									string of all elements.
*		Jason Rohrer	7-26-2005	Added template <> to explicitly specialized
*									getElementString.
*		Jason Rohrer	1-9-2009	Added setElementString method.
*		Jason Rohrer	9-7-2009	Fixed int types.
*									Added appendElementString.
*		Jason Rohrer	11-11-2009	Changed second deleteElement to allow
*                                   SimpleVectors containing ints.
*		Jason Rohrer	12-23-2009	New push_back for arrays.
*		Jason Rohrer	1-5-2010	Reduced default size to conserve memory.
*		Jason Rohrer	1-12-2010	Added copy constructor and assignment 
*                                   operator.
*		Jason Rohrer	1-16-2010	Fixed bugs in new constructor/operator.
*		Jason Rohrer	1-18-2010	Fixed memmove/memcpy bugs.
*		Jason Rohrer	1-28-2010	Data protected for subclass access.
*		Jason Rohrer	4-28-2010	Fast version of getElement.
*		Jason Rohrer	5-14-2010	String parameters as const to fix warnings.
*/

#include "minorGems/common.h"



#ifndef SIMPLEVECTOR_INCLUDED
#define SIMPLEVECTOR_INCLUDED

#include <string.h>		// for memory moving functions


const int defaultStartSize = 2;

template <class Type>
class SimpleVector {
	public:
	
		SimpleVector();		// create an empty vector
		SimpleVector(int sizeEstimate); // create an empty vector with a size estimate
		
		~SimpleVector();
		
        
        // copy constructor
        SimpleVector( const SimpleVector &inCopy );
        
        // assignment operator
        SimpleVector & operator = (const SimpleVector &inOther );
        


		
		void push_back(Type x);		// add x to the end of the vector

        // add array of elements to the end of the vector
		void push_back(Type *inArray, int inLength);		
		

		Type *getElement(int index);		// get a ptr to element at index in vector

		Type *getElementFast(int index); // no bounds checking
		
		
		int size();		// return the number of allocated elements in the vector
		
		bool deleteElement(int index);		// delete element at an index in vector
		
		/**
		 * Deletes a particular element.  Deletes the first element
		 * in vector == to inElement.
		 *
		 * @param inElement the element to delete.
		 *
		 * @return true iff an element was deleted.
		 */
		bool deleteElementEqualTo( Type inElement );



		/**
		 * Gets the index of a particular element.  Gets the index of the
		 * first element in vector == to inElement.
		 *
		 * @param inElement the element to get the index of.
		 *
		 * @return the index if inElement, or -1 if inElement is not found.
		 */
		int getElementIndex( Type inElement );

		
		
		void deleteAll();		// delete all elements from vector


        
		/**
		 * Gets the elements as an array.
		 *
		 * @return the a new array containing all elements in this vector.
         *   Must be destroyed by caller, though elements themselves are
         *   not copied.
		 */
		Type *getElementArray();


        
        /**
		 * Gets the char elements as a \0-terminated string.
		 *
		 * @return a \0-terminated string containing all elements in this
         *   vector.
         *   Must be destroyed by caller.
		 */
		char *getElementString();


        /**
		 * Sets the char elements as a \0-terminated string.
		 *
		 * @param inString a \0-terminated string containing all elements to 
         *   set this vector with.
         *   Must be destroyed by caller.
		 */
		void setElementString( const char *inString );



        /**
		 * Appends chars from a \0-terminated string.
		 *
		 * @param inString a \0-terminated string containing all elements to 
         *   append to this vector.
         *   Must be destroyed by caller.
		 */
		void appendElementString( const char *inString );


        
	protected:
		Type *elements;
		int numFilledElements;
		int maxSize;
		int minSize;	// number of allocated elements when vector is empty
		};
		
		
template <class Type>		
inline SimpleVector<Type>::SimpleVector() {
	elements = new Type[defaultStartSize];
	numFilledElements = 0;
	maxSize = defaultStartSize;
	minSize = defaultStartSize;
	}

template <class Type>
inline SimpleVector<Type>::SimpleVector(int sizeEstimate) {
	elements = new Type[sizeEstimate];
	numFilledElements = 0;
	maxSize = sizeEstimate;
	minSize = sizeEstimate;
	}
	
template <class Type>	
inline SimpleVector<Type>::~SimpleVector() {
	delete [] elements;
	}	



// copy constructor
template <class Type>
inline SimpleVector<Type>::SimpleVector( const SimpleVector<Type> &inCopy )
        : elements( new Type[ inCopy.maxSize ] ),
          numFilledElements( inCopy.numFilledElements ),
          maxSize( inCopy.maxSize ), minSize( inCopy.minSize ) {
    
    // if these objects contain pointers to stack, etc, this is not 
    // going to work (not a deep copy)
    // because it won't invoke the copy constructors of the objects!
    //memcpy( elements, inCopy.elements, sizeof( Type ) * numFilledElements );
    
    for( int i=0; i<inCopy.numFilledElements; i++ ) {
        elements[i] = inCopy.elements[i];
        }

    }



// assignment operator
template <class Type>
inline SimpleVector<Type> & SimpleVector<Type>::operator = (
    const SimpleVector<Type> &inOther ) {
    
    // pattern found on wikipedia:

    // avoid self-assignment
    if( this != &inOther )  {
        
        // 1: allocate new memory and copy the elements
        Type *newElements = new Type[ inOther.maxSize ];

        // again, memcpy doesn't work here, because it doesn't invoke
        // copy constructor on contained object
        /*memcpy( newElements, inOther.elements, 
                sizeof( Type ) * inOther.numFilledElements );
        */
        for( int i=0; i<inOther.numFilledElements; i++ ) {
            newElements[i] = inOther.elements[i];
            }


        // 2: deallocate old memory
        delete [] elements;
 
        // 3: assign the new memory to the object
        elements = newElements;
        numFilledElements = inOther.numFilledElements;
        maxSize = inOther.maxSize;
        minSize = inOther.minSize;
        }

    // by convention, always return *this
    return *this;
    }






template <class Type>
inline int SimpleVector<Type>::size() {
	return numFilledElements;
	}

template <class Type>
inline Type *SimpleVector<Type>::getElement(int index) {
	if( index < numFilledElements && index >=0 ) {
		return &(elements[index]);
		}
	else return NULL;
	}


template <class Type>
inline Type *SimpleVector<Type>::getElementFast(int index) {
    return &(elements[index]);
	}
	

template <class Type>
inline bool SimpleVector<Type>::deleteElement(int index) {
	if( index < numFilledElements) {	// if index valid for this vector
		
		if( index != numFilledElements - 1)  {	
            // this spot somewhere in middle
		
            

            // memmove NOT okay here, because it leaves shallow copies
            // behind that cause errors when the whole element array is 
            // destroyed.

            /*
			// move memory towards front by one spot
			int sizeOfElement = sizeof(Type);
		
			int numBytesToMove = sizeOfElement*(numFilledElements - (index+1));
		
			Type *destPtr = &(elements[index]);
			Type *srcPtr = &(elements[index+1]);
		
			memmove( (void *)destPtr, (void *)srcPtr, 
                    (unsigned int)numBytesToMove);
            */


            for( int i=index+1; i<numFilledElements; i++ ) {
                elements[i - 1] = elements[i];
                }
			}
			
		numFilledElements--;	// one less element in vector
		return true;
		}
	else {				// index not valid for this vector
		return false;
		}
	}


template <class Type>
inline bool SimpleVector<Type>::deleteElementEqualTo( Type inElement ) {
	int index = getElementIndex( inElement );
	if( index != -1 ) {
		return deleteElement( index );
		}
	else {
		return false;
		}
	}



template <class Type>
inline int SimpleVector<Type>::getElementIndex( Type inElement ) {
	// walk through vector, looking for first match.
	for( int i=0; i<numFilledElements; i++ ) {
		if( elements[i] == inElement ) {
			return i;
			}
		}
	
	// no element found
	return -1;
	}



template <class Type>
inline void SimpleVector<Type>::deleteAll() {
	numFilledElements = 0;
	if( maxSize > minSize ) {		// free memory if vector has grown
		delete [] elements;
		elements = new Type[minSize];	// reallocate an empty vector
		maxSize = minSize;
		}
	}


template <class Type>
inline void SimpleVector<Type>::push_back(Type x)	{
	if( numFilledElements < maxSize) {	// still room in vector
		elements[numFilledElements] = x;
		numFilledElements++;
		}
	else {					// need to allocate more space for vector
		int newMaxSize = maxSize << 1;		// double size
		
        // NOTE:  memcpy does not work here, because it does not invoke
        // copy constructors on elements.
        // And then "delete []" below causes destructors to be invoked
        //  on old elements, which are shallow copies of new objects.

        Type *newAlloc = new Type[newMaxSize];
        /*
		unsigned int sizeOfElement = sizeof(Type);
		unsigned int numBytesToMove = sizeOfElement*(numFilledElements);
		

		// move into new space
		memcpy((void *)newAlloc, (void *) elements, numBytesToMove);
		*/

        // must use element-by-element assignment to invoke constructors
        for( int i=0; i<numFilledElements; i++ ) {
            newAlloc[i] = elements[i];
            }
        

		// delete old space
		delete [] elements;
		
		elements = newAlloc;
		maxSize = newMaxSize;	
		
		elements[numFilledElements] = x;
		numFilledElements++;	
		}
	}



template <class Type>
inline void SimpleVector<Type>::push_back(Type *inArray, int inLength)	{
    
    for( int i=0; i<inLength; i++ ) {
        push_back( inArray[i] );
        }
    }



template <class Type>
inline Type *SimpleVector<Type>::getElementArray() {
    Type *newAlloc = new Type[ numFilledElements ];

    // shallow copy not good enough!
    /*
    unsigned int sizeOfElement = sizeof( Type );
    unsigned int numBytesToCopy = sizeOfElement * numFilledElements;
    
    // copy into new space
    //memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy );
    */

    // use assignment to ensure that constructors are invoked on element copies
    for( int i=0; i<numFilledElements; i++ ) {
        newAlloc[i] = elements[i];
        }

    return newAlloc;
    }



template <>
inline char *SimpleVector<char>::getElementString() {
    char *newAlloc = new char[ numFilledElements + 1 ];
    unsigned int sizeOfElement = sizeof( char );
    unsigned int numBytesToCopy = sizeOfElement * numFilledElements;
		
    // memcpy fine here, since shallow copy good enough for chars
    // copy into new space
    memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy );

    newAlloc[ numFilledElements ] = '\0';
    
    return newAlloc;
    }


template <>
inline void SimpleVector<char>::appendElementString( const char *inString ) {
    // slow but correct
    
    unsigned int numChars = strlen( inString );
    for( unsigned int i=0; i<numChars; i++ ) {
        push_back( inString[i] );
        }
    }



template <>
inline void SimpleVector<char>::setElementString( const char *inString ) {
    deleteAll();

    appendElementString( inString );
    }






#endif