Class Hierarchy   Class Index   Method Index  

CHMvector.h

00001 #ifndef __CHM_VECTOR__
00002 #define __CHM_VECTOR__
00003 //---------------------------------------------------------------------------
00004 // Module: CHMvector
00005 //
00006 // Description:
00007 //
00008 // Simple templated reference vector class
00009 //
00010 // The objects stored in the template must support 
00011 // Item& operator=(const Item&)
00012 //
00013 // By default the vector will grow in chunks of 10 - however the grow factor
00014 // can be altered or made into a product - i.e. growing by a multiple of the
00015 // grow factor rather than a fixed step.  Growing is expensive -
00016 // time will be saved if the vector can be pre-sized.
00017 //
00018 // Last Edit Date: $Date: 2002-10-16 21:28:30 $
00019 //
00020 //---------------------------------------------------------------------------
00021 
00022 #include <CHM/CHMerrorClass.h>
00023 
00024 template<class Item>
00025 class CHMvector
00026 {
00027 public:
00028    CHMvector(size_t GrowFactor = 10,
00029              size_t InitialSize=0,
00030              CHMboolean GrowByDouble=false);
00031    ~CHMvector();
00032 
00033    Item& operator[](size_t Index);
00034    const Item& operator[](size_t Index) const;
00035 
00036    void insert(const Item& Value, size_t Index);
00037 
00038    void remove(size_t Index);
00039 
00040    size_t size() const;
00041 
00042    void resize(size_t NewSize);
00043 
00044    void clear();
00045 
00046    void push_back(const Item& Value);
00047    Item& pop_back();
00048    Item& back();
00049    CHMvector<Item>& operator=(const CHMvector<Item>& Original);
00050 private:
00051    size_t m_GrowBy;
00052    size_t m_Size;
00053    size_t m_Capacity;
00054 
00055    CHMboolean m_GrowByDouble;
00056 
00057    Item* m_pData;
00058 
00059    void grow(size_t RequiredSize);
00060 
00061    CHMvector(const CHMvector<Item>& Original) {}
00062 };
00063 
00064 template<class Item>
00065 CHMvector<Item>::CHMvector
00066 (
00067    size_t GrowBy,
00068    size_t InitialSize,
00069    CHMboolean GrowByDouble
00070 ) : m_GrowBy(GrowBy),
00071     m_Size(InitialSize),
00072     m_Capacity(InitialSize),
00073     m_GrowByDouble(GrowByDouble)
00074 {
00075    CHM_ASSERT(GrowBy > 0);
00076    if (m_Capacity > 0)
00077    {
00078       m_pData = new Item[m_Capacity];
00079    }
00080    else
00081    {
00082       m_pData = NULL;
00083    }
00084 }
00085 
00086 template<class Item>
00087 CHMvector<Item>::~CHMvector()
00088 {
00089    delete []m_pData;
00090 }
00091 
00092 template<class Item>
00093 void CHMvector<Item>::clear()
00094 {
00095    m_Size = 0;
00096 }
00097 
00098 template<class Item>
00099 Item& CHMvector<Item>::operator[](size_t Index)
00100 {
00101    CHM_ASSERT(Index < m_Size);
00102    return m_pData[Index];
00103 }
00104 
00105 template<class Item>
00106 const Item& CHMvector<Item>::operator[](size_t Index) const
00107 {
00108    CHM_ASSERT(Index < m_Size);
00109    return m_pData[Index];
00110 }
00111 
00112 template<class Item>
00113 size_t CHMvector<Item>::size() const
00114 {
00115    return m_Size;
00116 }
00117 
00118 template<class Item>
00119 void CHMvector<Item>::resize(size_t NewSize)
00120 {
00121    CHM_ASSERT(NewSize >= m_Size);
00122    if (NewSize == m_Size)
00123    {
00124       // no need to resize...
00125       return;
00126    }
00127    if (m_Capacity < NewSize)
00128    {
00129       grow(NewSize);
00130    }
00131    m_Size = NewSize;
00132 }
00133 
00134 template<class Item>
00135 void CHMvector<Item>::remove(size_t Index)
00136 {
00137    CHM_ASSERT(Index < m_Size);
00138    for(size_t ItemIndex = Index;
00139        ItemIndex < m_Size-1;
00140        ++ItemIndex)
00141    {
00142       m_pData[ItemIndex] = m_pData[ItemIndex+1];
00143    }
00144    m_Size--;
00145 }
00146 
00147 template<class Item>
00148 void CHMvector<Item>::insert(const Item& Value, size_t Index)
00149 {
00150    CHM_ASSERT(Index <= m_Size)
00151    if (m_Size == m_Capacity)
00152    {
00153        grow(m_Capacity+1);
00154    }
00155    CHM_ASSERT(m_Size < m_Capacity);
00156 
00157 
00158    for (size_t CopyIndex = m_Size;
00159         CopyIndex > Index;
00160         --CopyIndex)
00161    {
00162       m_pData[CopyIndex] = m_pData[CopyIndex-1];
00163    }
00164    m_pData[Index] = Value;
00165    m_Size++;
00166 }
00167 
00168 template<class Item>
00169 void CHMvector<Item>::push_back(const Item& Value)
00170 {
00171    if (m_Size == m_Capacity)
00172    {
00173       grow(m_Capacity+1);
00174    }
00175    CHM_ASSERT(m_Size < m_Capacity);
00176 
00177    m_pData[m_Size] = Value;
00178    m_Size++;
00179 }
00180 
00181 template<class Item>
00182 Item& CHMvector<Item>::pop_back()
00183 {
00184    CHM_ASSERT(m_Size > 0);
00185    m_Size--;
00186    return m_pData[m_Size];
00187 }
00188 
00189 template<class Item>
00190 Item& CHMvector<Item>::back()
00191 {
00192    CHM_ASSERT(m_Size > 0);
00193    return m_pData[m_Size-1];
00194 }
00195 
00196 template<class Item>
00197 void CHMvector<Item>::grow(size_t RequiredSize)
00198 {
00199    CHM_ASSERT(RequiredSize > 0);
00200    CHM_ASSERT(m_GrowBy > 0);
00201    size_t NewCapacity(m_Capacity);
00202    if (m_GrowByDouble)
00203    {
00204       if (NewCapacity == 0)
00205       {
00206          NewCapacity = 1;
00207       }
00208       while (NewCapacity < RequiredSize)
00209       {
00210          NewCapacity = m_GrowBy * NewCapacity;
00211       }
00212    }
00213    else
00214    {
00215       while (NewCapacity < RequiredSize)
00216       {
00217          NewCapacity = m_GrowBy + NewCapacity;
00218       }
00219    }
00220 
00221    Item* pNewData = new Item[NewCapacity];
00222    size_t ItemIndex;
00223    for(ItemIndex = 0;
00224        ItemIndex < m_Size;
00225        ItemIndex++)
00226    {
00227       pNewData[ItemIndex] = m_pData[ItemIndex];
00228    }
00229    delete []m_pData;
00230    m_pData = pNewData;
00231    m_Capacity = NewCapacity;
00232 }
00233 
00234 template<class Item>
00235 CHMvector<Item>& CHMvector<Item>::operator=(const CHMvector<Item>& Original)
00236 {
00237    m_GrowBy = Original.m_GrowBy;
00238    m_Size   = Original.m_Size;
00239    m_Capacity = Original.m_Capacity;
00240    m_GrowByDouble = Original.m_GrowByDouble;
00241    CHM_ASSERT(m_Size <= m_Capacity);
00242    delete []m_pData;
00243    m_pData = new Item[m_Capacity];
00244    for (size_t DataIndex = 0; DataIndex < m_Size; ++DataIndex)
00245    {
00246       m_pData[DataIndex] = Original.m_pData[DataIndex];
00247    }
00248    return *this; 
00249 }
00250 #endif // end of defensive include