blob: 7e648e7c9aeafe77ecaf79ec0456de1160944322 [file] [log] [blame]
/*
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Description: The Vector class is a generic container which acts
* much like an array. The Vector class handles dynamic sizing and
* resizing as well as performing bounds checking on each access. An
* "insertAtBottom" operation is supported to allow adding elements to
* the Vector much like you would add new elements to a linked list or
* queue.
*/
#ifndef VECTOR_H
#define VECTOR_H
#include "mem/gems_common/std-includes.hh"
template <class TYPE>
class Vector
{
public:
Vector();
explicit Vector(int initial_size); // Construct with an initial max size
~Vector();
const TYPE& ref(int index) const; // Get an element of the vector
TYPE& ref(int index); // Get an element of the vector
void clear(); // remove all elements of the vector
void sortVector(); // sort all elements using < operator
int size() const { return m_size; }
void setSize(int new_size); // Increase size, reallocates memory as needed
void expand(int num) { setSize(m_size+num); } // Increase size by num
void increaseSize(int new_size, const TYPE& reset); // and adds num of slots at the bottom set to reset value
void insertAtTop(const TYPE& element); // Increase size by one and set last element
// FIXME - WARNING: insertAtTop is currently O(n) and needs to be fixed
void insertAtBottom(const TYPE& element); // Increase size by one and set last element
TYPE sum() const; // Uses the += operator to sum all the elements of the vector
void deletePointers(); // Walks the Vector calling delete on all
// elements and sets them to NULL, can only
// be used when the TYPE is a pointer type.
void removeFromTop(int num); // removes elements from top
void print(ostream& out) const;
// Array Reference operator overloading
const TYPE& operator[](int index) const { return ref(index); }
TYPE& operator[](int index) { return ref(index); }
// Public copy constructor and assignment operator
Vector(const Vector& vec);
Vector<TYPE>& operator=(const Vector& vec);
private:
void grow(int new_max_size); // Expands vector to new_max_size
// Data members
TYPE* m_vec; // Array to hold the elements
int m_size; // Number of elements in use
int m_max_size; // Size of allocated array
};
template <class TYPE>
ostream& operator<<(ostream& out, const Vector<TYPE>& vec);
// *********************
template <class TYPE>
Vector<TYPE>::Vector()
{
m_size = 0;
m_max_size = 0;
m_vec = NULL;
}
template <class TYPE>
Vector<TYPE>::Vector(int initial_size)
{
m_size = 0;
m_max_size = initial_size;
m_vec = NULL;
grow(initial_size);
}
template <class TYPE>
Vector<TYPE>::~Vector()
{
delete [] m_vec;
}
template <class TYPE>
const TYPE& Vector<TYPE>::ref(int index) const
{
#ifndef NO_VECTOR_BOUNDS_CHECKS
assert(m_size != 0);
assert(index < m_size);
assert(index >= 0);
#endif
return m_vec[index];
}
template <class TYPE>
TYPE& Vector<TYPE>::ref(int index)
{
#ifndef NO_VECTOR_BOUNDS_CHECKS
assert(m_size != 0);
assert(index < m_size);
assert(index >= 0);
#endif
return m_vec[index];
}
template <class TYPE>
void Vector<TYPE>::setSize(int new_size)
{
// FIXME - this should also decrease or shrink the size of the array at some point.
if (new_size > m_max_size) {
grow(max((m_max_size+1)*2, new_size));
}
m_size = new_size;
#ifndef NO_VECTOR_BOUNDS_CHECKS
assert(m_size <= m_max_size);
assert(m_size >= 0);
#endif
}
template <class TYPE>
inline
void Vector<TYPE>::increaseSize(int new_size, const TYPE& reset)
{
assert(new_size >= m_size);
if (new_size >= m_max_size) {
grow(max((m_max_size+1)*2, new_size));
}
int old_size = m_size;
m_size = new_size;
for (int j = old_size; j < m_size; j++) {
ref(j) = reset;
}
#ifndef NO_VECTOR_BOUNDS_CHECKS
assert(m_size <= m_max_size);
assert(m_size >= 0);
#endif
}
template <class TYPE>
inline
void Vector<TYPE>::clear()
{
m_size = 0;
m_max_size = 0;
delete [] m_vec;
m_vec = NULL;
}
template <class TYPE>
inline
void Vector<TYPE>::sortVector()
{
sort(&m_vec[0], &m_vec[m_size]);
}
template <class TYPE>
inline
void Vector<TYPE>::insertAtTop(const TYPE& element)
{
setSize(m_size+1);
for (int i = m_size-1; i >= 1; i--) {
ref(i) = ref(i-1);
}
ref(0) = element;
}
template <class TYPE>
inline
void Vector<TYPE>::removeFromTop(int num)
{
if (num > m_size) {
num = m_size;
}
for (int i = 0; i < m_size - num; i++) {
m_vec[i] = m_vec[i+num];
}
m_size = m_size - num;
}
template <class TYPE>
void Vector<TYPE>::insertAtBottom(const TYPE& element)
{
setSize(m_size+1);
ref(m_size-1) = element;
}
template <class TYPE>
TYPE Vector<TYPE>::sum() const
{
assert(m_size > 0);
TYPE sum = ref(0);
for(int i=1; i<m_size; i++) {
sum += ref(i);
}
return sum;
}
template <class TYPE>
void Vector<TYPE>::deletePointers()
{
assert(m_size >= 0);
for(int i=0; i<m_size; i++) {
// FIXME this function should be non-member function, otherwise this
// prevent template instantiation for non-pointer types
//
// Also, there is warning of Switch.cc which use void* here
delete ref(i);
ref(i) = NULL;
}
}
template <class TYPE>
void Vector<TYPE>::print(ostream& out) const
{
out << "[ ";
for(int i=0; i<m_size; i++) {
if (i != 0) {
out << " ";
}
out << ref(i);
}
out << " ]";
out << flush;
}
// Copy constructor
template <class TYPE>
Vector<TYPE>::Vector(const Vector& vec)
{
// Setup the new memory
m_size = vec.m_size;
m_max_size = vec.m_max_size;
if (m_max_size != 0) {
m_vec = new TYPE[m_max_size];
assert(m_vec != NULL);
} else {
m_vec = NULL;
}
// Copy the elements of the array
for(int i=0; i<m_size; i++) {
m_vec[i] = vec.m_vec[i]; // Element copy
}
}
template <class TYPE>
Vector<TYPE>& Vector<TYPE>::operator=(const Vector& vec)
{
if (this == &vec) {
// assert(0);
} else {
// Free the old memory
delete [] m_vec;
// Setup the new memory
m_size = vec.m_size;
m_max_size = vec.m_max_size;
if (m_max_size != 0) {
m_vec = new TYPE[m_max_size];
assert(m_vec != NULL);
} else {
m_vec = NULL;
}
// Copy the elements of the array
for(int i=0; i<m_size; i++) {
m_vec[i] = vec.m_vec[i]; // Element copy
}
}
return *this;
}
template <class TYPE>
void Vector<TYPE>::grow(int new_max_size)
{
TYPE* temp_vec;
m_max_size = new_max_size;
if (new_max_size != 0) {
temp_vec = new TYPE[new_max_size];
assert(temp_vec != NULL);
} else {
temp_vec = NULL;
}
// Copy the elements of the array
for(int i=0; i<m_size; i++) {
temp_vec[i] = m_vec[i]; // Element copy
}
delete [] m_vec;
m_vec = temp_vec;
}
template <class TYPE>
ostream& operator<<(ostream& out, const Vector<TYPE>& vec)
{
vec.print(out);
return out;
}
#endif //VECTOR_H