// VECTOR.H // A template for a resizable vector // ////////////////////////////////////////////////////////////////////////////// // Projection Genomics Toolkit // Copyright (C) 2000-2001 by Jeremy Buhler, all rights reserved. // For licensing terms, please see the accompanying LICENSE file. // For information and bug reports, please contact jbuhler@cs.wustl.edu. ////////////////////////////////////////////////////////////////////////////// // // The vector data is reference counted, so a Vector object can be // treated as a "smart pointer" which may be copied around freely. A // Vector requires only one pointer's worth of storage when it is // empty. // // NOTE: list elements are copied once on insertion. // #ifndef __VECTOR_H #define __VECTOR_H template class Vector { private: // type of the actual vector data -- a ref-counted expansible vector class VectorData { public: VectorData(unsigned int initLength) : _length(0), refCount(0) { vec = new ValueT [initLength]; maxLength = initLength; } virtual ~VectorData(void) { if (vec) delete [] vec; } unsigned int length(void) const { return _length; } ValueT *elements(void) const { return vec; } // reference counting operations int addRef(void) { return ++refCount; } int delRef(void) { return --refCount; } // allocate and return ptr to new, empty element at the end of the vector ValueT *allocNext(void) { if (_length == maxLength) resize(maxLength * 2); return &(vec[_length++]); } // remove a value from the end of the vector void removeLast(void) { if (_length > 0) _length--; } // truncate a vector to at most a given length void truncate(unsigned int newLength) { if (_length > newLength) _length = newLength; } // Copy the concents of a second vector onto the end of this vector. // To avoid doing paying a quadratic cost for many small concatenations, // at least double the vector size whenever we must grow it // to accomodate a new concatenation, just as for add(). // void concat(const VectorData *other) { if (other) { unsigned int newLength = _length + other->_length; if (maxLength < newLength) { if (2 * maxLength < newLength) resize(newLength); else resize(2 * maxLength); } for (unsigned int j = 0; j < other->_length; j++) vec[_length + j] = other->vec[j]; _length += other->_length; } } // return a copy of ourselves VectorData *copy(void) const { VectorData *vd = new VectorData(_length); for (unsigned int j = 0; j < _length; j++) vd->vec[j] = vec[j]; vd->_length = _length; return vd; } private: ValueT *vec; unsigned int _length; unsigned int maxLength; int refCount; // increase the size of the vector to at least newSize void resize(unsigned int newLength) { ValueT *newVec = new ValueT [newLength]; for (unsigned int j = 0; j < _length; j++) newVec[j] = vec[j]; if (vec) delete [] vec; vec = newVec; maxLength = newLength; } }; VectorData *data; public: Vector(void) : data(0) {} Vector(const Vector &other) { data = other.data; if (data) data->addRef(); } Vector &operator=(const Vector &other) { if (data && data->delRef() == 0) delete data; data = other.data; if (data) data->addRef(); return *this; } ~Vector(void) { if (data && data->delRef() == 0) delete data; } unsigned int length(void) const { return (data ? data->length() : 0); } bool isEmpty(void) const { return (!data || data->length() == 0); } ValueT *elements(void) const { return (data ? data->elements() : 0); } ValueT &operator[](unsigned int j) const { return data->elements()[j]; } ValueT *allocNext(void) { // allocate list data lazily if (!data) { data = new VectorData(10); data->addRef(); } return data->allocNext(); } // add an element to the end of the vector ValueT &add(const ValueT &value) { ValueT *v = allocNext(); *v = value; return *v; } // remove the last element of the vector void removeLast(void) { if (data) { data->removeLast(); if (data->length() == 0) { if (data->delRef() == 0) delete data; data = 0; } } } // truncate the vector to at most the specified length void truncate(unsigned int newLength = 0) { if (newLength == 0) { if (data && data->delRef() == 0) { delete data; } data = 0; } else if (data) data->truncate(newLength); } // Concatenate a new vector onto ourselves. Vector concat(const Vector &other) { if (!data) *this = other.copy(); else data->concat(other.data); return *this; } // return a deep copy of the vector Vector copy(void) const { Vector other; if (data) { other.data = data->copy(); other.data->addRef(); } return other; } }; typedef Vector UIntVector; typedef Vector ULongVector; typedef Vector StringVector; #endif // __VECTOR_H