/* * Copyright 2002 Adrian Thurston <adriant@ragel.ca> */ /* This file is part of Aapl. * * Aapl is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * Aapl 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 Lesser General Public License for * more details. * * You should have received a copy of the GNU Lesser General Public License * along with Aapl; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _AAPL_VECTSIMP_H #define _AAPL_VECTSIMP_H #define Vector VectSimp #include "vectcommon.h" #undef Vector #ifdef AAPL_NAMESPACE namespace Aapl { #endif /** * \addtogroup vector * @{ */ /** \class VectSimp * \brief Dynamic array for classes with trivial initialization. * * VectSimp is a dynamic array that can be used only to contain simple data * types that do not have constructors and destructors such as integers and * pointers. The trivial initialization allows the use of memcpy for putting * data into the vector and consequently VectSimp offers a significant * performance increase over Vector. * * VectSimp supports inserting, overwriting and removing single or multiple * elements at once. * * VectSimp provides automatic resizing of allocated memory as needed and * offers different allocation schemes for controlling how the automatic * allocation is done. Two senses of the the length of the data is * maintained: the amount of raw memory allocated to the vector and the number * of actual elements in the vector. The various allocation schemes control * how the allocated space is changed in relation to the number of elements in * the vector. */ /*@}*/ /** \fn VectSimp::VectSimp( long size ) * \brief Create a vector with a specified number of initial elements. * * The new elements are not initialized. The initial space allocation is zero * and it is grown according to the up allocation scheme used. If a linear * resizer is used, the step defaults to 256 units of T. For a runtime vector * both up and down allocation schemes default to Exponential. * * This constructor is not of any use to a vector with a constant up resizing * scheme as it starts with no space allocated and is unable to grow. It will * assertion fail with a non-zero size value. * */ /** \fn VectSimp::VectSimp( long size, long allocLen ) * \brief Create a vector with a specified number of initial elements and * allocation. * * The new elements are not initialized. If the size is greater than * allocLen, then the space will be grown according to the allocation * scheme. Both size and allocLen are in units of T. If a linear resizer * is used, the step defaults to 256 units of T. For a runtime vector both up * and down allocation schemes default to Exponential. */ /** * \brief Perform a deep copy of the vector. * * The contents of the other vector are copied into this vector. This vector * gets the same allocation size as the other vector. Memcpy is used to put * data into this vector. */ template<class T, class Resize> VectSimp<T, Resize>:: VectSimp(const VectSimp<T, Resize> &b) { BaseTable::tabLen = b.tabLen; BaseTable::allocLen = b.allocLen; if ( BaseTable::allocLen > 0 ) { /* Alloc the space for the data. */ BaseTable::data = (T*) malloc(sizeof(T)*BaseTable::allocLen); if ( BaseTable::data == NULL ) throw std::bad_alloc(); /* Copy the data in. */ memcpy( BaseTable::data, b.data, sizeof(T)*BaseTable::tabLen ); } else { /* Noting is allocated. */ BaseTable::data = NULL; } } /** \fn VectSimp::~VectSimp() * \brief Free all memory used by the vector. * * The vector is reset to zero elements. The space allocated for the vector is * freed. */ /** * \brief Free all memory used by the vector. * * The vector is reset to zero elements. The space allocated for the vector is * freed. */ template<class T, class Resize> void VectSimp<T, Resize>:: empty() { if ( BaseTable::data != NULL ) { /* Free the data space. */ free( BaseTable::data ); BaseTable::data = NULL; BaseTable::tabLen = BaseTable::allocLen = 0; } } /** \fn VectSimp::setAs(const T &val) * \brief Set the contents of the vector to be val exactly. * * The vector becomes one element in length. Existing elements not * uninitialized. Memcpy is used to place the new item in the vector. */ /** * \brief Set the contents of the vector to be len elements exactly. * * The vector becomes len elements in length. Any existing elements are not * uninitialzed. Memcpy is used to place the new elements in the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: setAs(const T *val, long len) { /* Adjust the allocated length. */ if ( len < BaseTable::tabLen ) downResize(len); else if ( len > BaseTable::tabLen ) upResize(len); /* Set the new data length to exactly len. */ BaseTable::tabLen = len; /* Copy data in. */ memcpy( BaseTable::data, val, sizeof(T)*len ); } /** \fn VectSimp::setAs(const VectSimp<T, Resize> &v) * \brief Set the vector to exactly the contents of another vector. * * The vector becomes v.tabLen elements in length. Any existing elements * are not uninitialized. Memcpy is used to place the new elements in the * vector. */ /** * \brief Set the vector to len copies of item. * * The vector becomes len elements in length. Any existing elements are not * uninitialized. The assignment operator is used to copy the item into the * vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: setAsDup(const T &item, long len) { /* Adjust the allocated length. */ if ( len < BaseTable::tabLen ) downResize(len); else if ( len > BaseTable::tabLen ) upResize(len); /* Set the new data length to exactly len. */ BaseTable::tabLen = len; /* Copy the data item in one at a time. */ T *dst = BaseTable::data; for ( long i = 0; i < len; i++, dst++ ) *dst = item; } /** \fn VectSimp::setAsNew() * \brief Set the vector to exactly one new item. * * The vector becomes one element in length. Any existing elements are not * uninitialized. The new item is not initialized. */ /** * \brief Set the vector to exactly len new items. * * The vector becomes len elements in length. Any existing elements are not * uninitialized. The new items are not initialized. */ template<class T, class Resize> void VectSimp<T, Resize>:: setAsNew(long len) { /* Adjust the allocated length. */ if ( len < BaseTable::tabLen ) downResize(len); else if ( len > BaseTable::tabLen ) upResize(len); /* Set the new data length to exactly len. */ BaseTable::tabLen = len; } /** \fn VectSimp::replace(long pos, const T &val) * \brief Replace one element at position pos. * * If there is an existing element at position pos (if pos is less than the * length of the vector) then it is not uninitialized in any way. Memcpy is * used to place the new element into the vector. If pos is greater than the * length of the vector then undefined behaviour results. If pos is negative * then it is treated as an offset relative to the length of the vector. */ /** * \brief Replace len elements at position pos. * * If there are existing elements at the positions to be replaced, then they * are not uninitialized in any way. Memcpy is used to place the new elements * into the vector. It is allowable for the pos and length to specify a * replacement that overwrites existing elements and creates new ones. If pos * is greater than the length of the vector then undefined behaviour results. * If pos is negative, then it is treated as an offset relative to the length * of the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: replace(long pos, const T *val, long len) { /* If we are given a negative position to replace at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* The end is the one past the last item that we want * to write to. */ long endPos = pos + len; /* Make sure we have enough space. */ if ( endPos > BaseTable::tabLen ) { upResize( endPos ); /* Set the new length. */ BaseTable::tabLen = endPos; } /* Copy data in. */ memcpy( BaseTable::data + pos, val, sizeof(T)*len ); } /** \fn VectSimp::replace(long pos, const VectSimp<T, Resize> &v) * \brief Replace at position pos with all the elements of another vector. * * Replace at position pos with all the elements of another vector. The other * vector is left unchanged. If there are existing elements at the positions * to be replaced then they are not uninitialized in any way. Memcpy is used * to place the elements into this vector. It is allowable for the pos and * length of the other vector to specify a replacement that overwrites * existing elements and creates new ones. If pos is greater than the length * of the vector then undefined behaviour results. If pos is negative, then it * is treated as an offset relative to the length of the vector. */ /** * \brief Replace at position pos with len copies of an item. * * If there are existing elements at the positions to be replaced then they * are not uninitialized in any way. The assignment operator is used to place * the item into the vector. It is allowable for the pos and length to specify * a replacement that overwrites existing elements and creates new ones. If * pos is greater than the length of the vector then undefined behaviour * results. If pos is negative, then it is treated as an offset relative to * the length of the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: replaceDup(long pos, const T &item, long len) { /* If we are given a negative position to replace at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* The end is the one past the last item that we want * to write to. */ long endPos = pos + len; /* Make sure we have enough space. */ if ( endPos > BaseTable::tabLen ) { upResize( endPos ); /* Set the new length. */ BaseTable::tabLen = endPos; } /* Copy the data item in one at a time. */ T *dst = BaseTable::data + pos; for ( long i = 0; i < len; i++, dst++ ) *dst = item; } /** \fn VectSimp::replaceNew(long pos) * \brief Replace at position pos with one new element. * * If there is an existing element at the position to be replaced (pos is less * than the length of the vector) then the element is not uninitialized in any * way. The new item is not initialized. If pos is greater than the length of * the vector then undefined behaviour results. If pos is negative, then it is * treated as an offset relative to the length of the vector. */ /** * \brief Replace at position pos with len new elements. * * If there are existing elements at the positions to be replaced then the * elements are not uninitialized in any way. The new items are not * initialized. It is allowable for the pos and length to specify a * replacement that overwrites existing elements and creates new ones. If pos * is greater than the length of the vector then undefined behaviour results. * If pos is negative, then it is treated as an offset relative to the length * of the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: replaceNew(long pos, long len) { /* If we are given a negative position to replace at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* The end is the one past the last item that we want * to write to. */ long endPos = pos + len; /* Make sure we have enough space. */ if ( endPos > BaseTable::tabLen ) { upResize( endPos ); /* Set the new length. */ BaseTable::tabLen = endPos; } } /** \fn VectSimp::remove(long pos) * \brief Remove one element at position pos. * * The space used by the element is not uninitialized in any way. Elements to * the right of pos are shifted one space to the left to take up the free * space. If pos is greater than or equal to the length of the vector then * undefined behavior results. If pos is negative then it is treated as an * offset relative to the length of the vector. */ /** * \brief Remove len elements at position pos. * * The space used by the elements is not uninitialized in any way. Elements to * the right of pos are shifted len spaces to the left to take up the free * space. If pos is greater than or equal to the length of the vector then * undefined behavior results. If pos is negative then it is treated as an * offset relative to the length of the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: remove(long pos, long len) { long newLen, lenToSlideOver, endPos; /* If we are given a negative position to remove at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* The first position after the last item deleted. */ endPos = pos + len; /* The new data length. */ newLen = BaseTable::tabLen - len; /* The place in the data we are deleting at. */ T *dst = BaseTable::data + pos; /* Shift data over if necessary. */ lenToSlideOver = BaseTable::tabLen - endPos; if ( len > 0 && lenToSlideOver > 0 ) memmove(dst, dst + len, sizeof(T)*lenToSlideOver); /* Shrink the data if necessary. */ downResize( newLen ); /* Set the new data length. */ BaseTable::tabLen = newLen; } /** \fn VectSimp::insert(long pos, const T &val) * \brief Insert one element at position pos. * * Elements in the vector from pos onward are shifted one space to the right. * Memcop is used to place the element into the vector. If pos is greater than * the length of the vector then undefined behaviour results. If pos is * negative then it is treated as an offset relative to the length of the * vector. */ /** * \brief Insert len elements at position pos. * * Elements in the vector from pos onward are shifted len spaces to the right. * Memcpy is used to place the elements in the vector. If pos is greater than * the length of the vector then undefined behaviour results. If pos is * negative then it is treated as an offset relative to the length of the * vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: insert(long pos, const T *val, long len) { /* If we are given a negative position to insert at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* Calculate the new length. */ long newLen = BaseTable::tabLen + len; /* Up resize, we are growing. */ upResize( newLen ); /* Shift over data at insert spot if needed. */ if ( len > 0 && pos < BaseTable::tabLen ) { memmove(BaseTable::data + pos + len, BaseTable::data + pos, sizeof(T)*(BaseTable::tabLen-pos)); } /* Copy data in. */ memcpy( BaseTable::data + pos, val, sizeof(T)*len ); /* Set the new length. */ BaseTable::tabLen = newLen; } /** \fn VectSimp::insert(long pos, const VectSimp &v) * \brief Insert all the elements from another vector at position pos. * * Elements in this vector from pos onward are shifted v.tabLen spaces to * the right. Memcpy is used to copy the elements into this vector. The other * vector is left unchanged. If pos is off the end of the vector, then * undefined behaviour results. If pos is negative then it is treated as an * offset relative to the length of the vector. Equivalent to * vector.insert(pos, other.data, other.tabLen). */ /** * \brief Insert len copies of item at position pos. * * Elements in the vector from pos onward are shifted len spaces to the right. * The assignment operator is used to place the element into vector. If pos is * greater than the length of the vector then undefined behaviour results. If * pos is negative then it is treated as an offset relative to the length of * the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: insertDup(long pos, const T &item, long len) { /* If we are given a negative position to insert at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* Calculate the new length. */ long newLen = BaseTable::tabLen + len; /* Up resize, we are growing. */ upResize( newLen ); /* Shift over data at insert spot if needed. */ if ( len > 0 && pos < BaseTable::tabLen ) { memmove(BaseTable::data + pos + len, BaseTable::data + pos, sizeof(T)*(BaseTable::tabLen-pos)); } /* Copy the data item in one at a time. */ T *dst = BaseTable::data + pos; for ( long i = 0; i < len; i++, dst++ ) *dst = item; /* Set the new length. */ BaseTable::tabLen = newLen; } /** \fn VectSimp::insertNew(long pos) * \brief Insert one new element using the default constrcutor. * * Elements in the vector from pos onward are shifted one space to the right. * The new element is not initialized. If pos is greater than the length of * the vector then undefined behaviour results. If pos is negative then it is * treated as an offset relative to the length of the vector. */ /** * \brief Insert len new elements using the default constrcutor. * * Elements in the vector from pos onward are shifted len spaces to the right. * The new items are not initialized. If pos is greater than the length of the * vector then undefined behaviour results. If pos is negative then it is * treated as an offset relative to the length of the vector. */ template<class T, class Resize> void VectSimp<T, Resize>:: insertNew(long pos, long len) { /* If we are given a negative position to insert at then * treat it as a position relative to the length. */ if ( pos < 0 ) pos = BaseTable::tabLen + pos; /* Calculate the new length. */ long newLen = BaseTable::tabLen + len; /* Up resize, we are growing. */ upResize( newLen ); /* Shift over data at insert spot if needed. */ if ( len > 0 && pos < BaseTable::tabLen ) { memmove(BaseTable::data + pos + len, BaseTable::data + pos, sizeof(T)*(BaseTable::tabLen-pos)); } /* Set the new length. */ BaseTable::tabLen = newLen; } /** \fn VectSimp::append(const T &val) * \brief Append one elment to the end of the vector. * * Memcpy is used to place the element in the vector. */ /** \fn VectSimp::append(const T *val, long len) * \brief Append len elements to the end of the vector. * * Memcpy is used to place the elements in the vector. */ /** \fn VectSimp::append(const VectSimp &v) * \brief Append the contents of another vector. * * The other vector is left unchanged. Memcpy is used to place the elements in * the vector. */ /** \fn VectSimp::appendDup(const T &item, long len) * \brief Append len copies of item. * * The assignment operator is used to place the item in the vector. */ /** \fn VectSimp::appendNew() * \brief Append a single newly created item. * * The new element is not initialized. */ /** \fn VectSimp::appendNew(long len) * \brief Append len newly created items. * * The new elements are not initialized. */ /** \fn VectSimp::prepend(const T &val) * \brief Prepend one elment to the front of the vector. * * Memcpy is used to place the element in the vector. */ /** \fn VectSimp::prepend(const T *val, long len) * \brief Prepend len elements to the front of the vector. * * Memcpy is used to place the elements in the vector. */ /** \fn VectSimp::prepend(const VectSimp &v) * \brief Prepend the contents of another vector. * * The other vector is left unchanged. Memcpy is used to place the elements in * the vector. */ /** \fn VectSimp::prependDup(const T &item, long len) * \brief Prepend len copies of item. * * The assignment operator is used to place the item in the vector. */ /** \fn VectSimp::prependNew() * \brief Prepend a single newly created item. * * The new element is not initialized. */ /** \fn VectSimp::prependNew(long len) * \brief Prepend len newly created items. * * The new elements are not initialized. */ #ifdef AAPL_NAMESPACE } #endif #endif /* _AAPL_VECTSIMP_H */

Generated by Doxygen 1.6.0 Back to index