Home | History | Annotate | Download | only in Gimpact
      1 #ifndef GIM_ARRAY_H_INCLUDED
      2 #define GIM_ARRAY_H_INCLUDED
      3 /*! \file gim_array.h
      4 \author Francisco Leon Najera
      5 */
      6 /*
      7 -----------------------------------------------------------------------------
      8 This source file is part of GIMPACT Library.
      9 
     10 For the latest info, see http://gimpact.sourceforge.net/
     11 
     12 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
     13 email: projectileman (at) yahoo.com
     14 
     15  This library is free software; you can redistribute it and/or
     16  modify it under the terms of EITHER:
     17    (1) The GNU Lesser General Public License as published by the Free
     18        Software Foundation; either version 2.1 of the License, or (at
     19        your option) any later version. The text of the GNU Lesser
     20        General Public License is included with this library in the
     21        file GIMPACT-LICENSE-LGPL.TXT.
     22    (2) The BSD-style license that is included with this library in
     23        the file GIMPACT-LICENSE-BSD.TXT.
     24    (3) The zlib/libpng license that is included with this library in
     25        the file GIMPACT-LICENSE-ZLIB.TXT.
     26 
     27  This library is distributed in the hope that it will be useful,
     28  but WITHOUT ANY WARRANTY; without even the implied warranty of
     29  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
     30  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
     31 
     32 -----------------------------------------------------------------------------
     33 */
     34 
     35 #include "gim_memory.h"
     36 
     37 
     38 #define GIM_ARRAY_GROW_INCREMENT 2
     39 #define GIM_ARRAY_GROW_FACTOR 2
     40 
     41 //!	Very simple array container with fast access and simd memory
     42 template<typename T>
     43 class gim_array
     44 {
     45 public:
     46 //! properties
     47 //!@{
     48     T *m_data;
     49     GUINT m_size;
     50     GUINT m_allocated_size;
     51 //!@}
     52 //! protected operations
     53 //!@{
     54 
     55     inline void destroyData()
     56 	{
     57 	    m_allocated_size = 0;
     58 		if(m_data==NULL) return;
     59 		gim_free(m_data);
     60 		m_data = NULL;
     61 	}
     62 
     63 	inline bool resizeData(GUINT newsize)
     64 	{
     65 		if(newsize==0)
     66 		{
     67 			destroyData();
     68 			return true;
     69 		}
     70 
     71 		if(m_size>0)
     72 		{
     73             m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
     74 		}
     75 		else
     76 		{
     77 		    m_data = (T*)gim_alloc(newsize*sizeof(T));
     78 		}
     79 		m_allocated_size = newsize;
     80 		return true;
     81 	}
     82 
     83 	inline bool growingCheck()
     84 	{
     85 		if(m_allocated_size<=m_size)
     86 		{
     87 		    GUINT requestsize = m_size;
     88 		    m_size = m_allocated_size;
     89 			if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
     90 		}
     91 		return true;
     92 	}
     93 
     94 //!@}
     95 //! public operations
     96 //!@{
     97     inline  bool reserve(GUINT size)
     98     {
     99         if(m_allocated_size>=size) return false;
    100         return resizeData(size);
    101     }
    102 
    103     inline void clear_range(GUINT start_range)
    104     {
    105         while(m_size>start_range)
    106         {
    107             m_data[--m_size].~T();
    108         }
    109     }
    110 
    111     inline void clear()
    112     {
    113         if(m_size==0)return;
    114         clear_range(0);
    115     }
    116 
    117     inline void clear_memory()
    118     {
    119         clear();
    120         destroyData();
    121     }
    122 
    123     gim_array()
    124     {
    125         m_data = 0;
    126         m_size = 0;
    127         m_allocated_size = 0;
    128     }
    129 
    130     gim_array(GUINT reservesize)
    131     {
    132         m_data = 0;
    133         m_size = 0;
    134 
    135         m_allocated_size = 0;
    136         reserve(reservesize);
    137     }
    138 
    139     ~gim_array()
    140     {
    141         clear_memory();
    142     }
    143 
    144     inline GUINT size() const
    145     {
    146         return m_size;
    147     }
    148 
    149     inline GUINT max_size() const
    150     {
    151         return m_allocated_size;
    152     }
    153 
    154     inline T & operator[](size_t i)
    155 	{
    156 		return m_data[i];
    157 	}
    158 	inline  const T & operator[](size_t i) const
    159 	{
    160 		return m_data[i];
    161 	}
    162 
    163     inline T * pointer(){ return m_data;}
    164     inline const T * pointer() const
    165     { return m_data;}
    166 
    167 
    168     inline T * get_pointer_at(GUINT i)
    169 	{
    170 		return m_data + i;
    171 	}
    172 
    173 	inline const T * get_pointer_at(GUINT i) const
    174 	{
    175 		return m_data + i;
    176 	}
    177 
    178 	inline T & at(GUINT i)
    179 	{
    180 		return m_data[i];
    181 	}
    182 
    183 	inline const T & at(GUINT i) const
    184 	{
    185 		return m_data[i];
    186 	}
    187 
    188 	inline T & front()
    189 	{
    190 		return *m_data;
    191 	}
    192 
    193 	inline const T & front() const
    194 	{
    195 		return *m_data;
    196 	}
    197 
    198 	inline T & back()
    199 	{
    200 		return m_data[m_size-1];
    201 	}
    202 
    203 	inline const T & back() const
    204 	{
    205 		return m_data[m_size-1];
    206 	}
    207 
    208 
    209 	inline void swap(GUINT i, GUINT j)
    210 	{
    211 	    gim_swap_elements(m_data,i,j);
    212 	}
    213 
    214 	inline void push_back(const T & obj)
    215 	{
    216 	    this->growingCheck();
    217 	    m_data[m_size] = obj;
    218 	    m_size++;
    219 	}
    220 
    221 	//!Simply increase the m_size, doesn't call the new element constructor
    222 	inline void push_back_mem()
    223 	{
    224 	    this->growingCheck();
    225 	    m_size++;
    226 	}
    227 
    228 	inline void push_back_memcpy(const T & obj)
    229 	{
    230 	    this->growingCheck();
    231 	    irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
    232 	    m_size++;
    233 	}
    234 
    235 	inline void pop_back()
    236 	{
    237 	    m_size--;
    238         m_data[m_size].~T();
    239 	}
    240 
    241 	//!Simply decrease the m_size, doesn't call the deleted element destructor
    242 	inline void pop_back_mem()
    243 	{
    244 	    m_size--;
    245 	}
    246 
    247     //! fast erase
    248 	inline void erase(GUINT index)
    249 	{
    250 	    if(index<m_size-1)
    251 	    {
    252 	        swap(index,m_size-1);
    253 	    }
    254 	    pop_back();
    255 	}
    256 
    257 	inline void erase_sorted_mem(GUINT index)
    258 	{
    259 	    m_size--;
    260 	    for(GUINT i = index;i<m_size;i++)
    261 	    {
    262 	        gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
    263 	    }
    264 	}
    265 
    266 	inline void erase_sorted(GUINT index)
    267 	{
    268 	    m_data[index].~T();
    269 	    erase_sorted_mem(index);
    270 	}
    271 
    272 	inline void insert_mem(GUINT index)
    273 	{
    274 	    this->growingCheck();
    275 	    for(GUINT i = m_size;i>index;i--)
    276 	    {
    277 	        gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
    278 	    }
    279 	    m_size++;
    280 	}
    281 
    282 	inline void insert(const T & obj,GUINT index)
    283 	{
    284 	    insert_mem(index);
    285 	    m_data[index] = obj;
    286 	}
    287 
    288 	inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T())
    289 	{
    290 	    if(size>m_size)
    291 	    {
    292             reserve(size);
    293             if(call_constructor)
    294             {
    295                 while(m_size<size)
    296                 {
    297                     m_data[m_size] = fillData;
    298                     m_size++;
    299                 }
    300             }
    301             else
    302             {
    303             	m_size = size;
    304             }
    305 	    }
    306 	    else if(size<m_size)
    307 	    {
    308 	        if(call_constructor) clear_range(size);
    309 	        m_size = size;
    310 	    }
    311 	}
    312 
    313 	inline void refit()
    314 	{
    315 	    resizeData(m_size);
    316 	}
    317 
    318 };
    319 
    320 
    321 
    322 
    323 
    324 #endif // GIM_CONTAINERS_H_INCLUDED
    325