325 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			325 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #ifndef GIM_ARRAY_H_INCLUDED
 | ||
|  | #define GIM_ARRAY_H_INCLUDED
 | ||
|  | /*! \file gim_array.h
 | ||
|  | \author Francisco Leon Najera | ||
|  | */ | ||
|  | /*
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | This source file is part of GIMPACT Library. | ||
|  | 
 | ||
|  | For the latest info, see http://gimpact.sourceforge.net/
 | ||
|  | 
 | ||
|  | Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. | ||
|  | email: projectileman@yahoo.com | ||
|  | 
 | ||
|  |  This library is free software; you can redistribute it and/or | ||
|  |  modify it under the terms of EITHER: | ||
|  |    (1) 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. The text of the GNU Lesser | ||
|  |        General Public License is included with this library in the | ||
|  |        file GIMPACT-LICENSE-LGPL.TXT. | ||
|  |    (2) The BSD-style license that is included with this library in | ||
|  |        the file GIMPACT-LICENSE-BSD.TXT. | ||
|  |    (3) The zlib/libpng license that is included with this library in | ||
|  |        the file GIMPACT-LICENSE-ZLIB.TXT. | ||
|  | 
 | ||
|  |  This library 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 files | ||
|  |  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. | ||
|  | 
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | */ | ||
|  | 
 | ||
|  | #include "gim_memory.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define GIM_ARRAY_GROW_INCREMENT 2
 | ||
|  | #define GIM_ARRAY_GROW_FACTOR 2
 | ||
|  | 
 | ||
|  | //!	Very simple array container with fast access and simd memory
 | ||
|  | template<typename T> | ||
|  | class gim_array | ||
|  | { | ||
|  | public: | ||
|  | //! properties
 | ||
|  | //!@{
 | ||
|  |     T *m_data; | ||
|  |     GUINT m_size; | ||
|  |     GUINT m_allocated_size; | ||
|  | //!@}
 | ||
|  | //! protected operations
 | ||
|  | //!@{
 | ||
|  | 
 | ||
|  |     inline void destroyData() | ||
|  | 	{ | ||
|  | 	    m_allocated_size = 0; | ||
|  | 		if(m_data==NULL) return; | ||
|  | 		gim_free(m_data); | ||
|  | 		m_data = NULL; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline bool resizeData(GUINT newsize) | ||
|  | 	{ | ||
|  | 		if(newsize==0) | ||
|  | 		{ | ||
|  | 			destroyData(); | ||
|  | 			return true; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if(m_size>0) | ||
|  | 		{ | ||
|  |             m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T)); | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 		    m_data = (T*)gim_alloc(newsize*sizeof(T)); | ||
|  | 		} | ||
|  | 		m_allocated_size = newsize; | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline bool growingCheck() | ||
|  | 	{ | ||
|  | 		if(m_allocated_size<=m_size) | ||
|  | 		{ | ||
|  | 		    GUINT requestsize = m_size; | ||
|  | 		    m_size = m_allocated_size; | ||
|  | 			if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false; | ||
|  | 		} | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | //!@}
 | ||
|  | //! public operations
 | ||
|  | //!@{
 | ||
|  |     inline  bool reserve(GUINT size) | ||
|  |     { | ||
|  |         if(m_allocated_size>=size) return false; | ||
|  |         return resizeData(size); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline void clear_range(GUINT start_range) | ||
|  |     { | ||
|  |         while(m_size>start_range) | ||
|  |         { | ||
|  |             m_data[--m_size].~T(); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     inline void clear() | ||
|  |     { | ||
|  |         if(m_size==0)return; | ||
|  |         clear_range(0); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline void clear_memory() | ||
|  |     { | ||
|  |         clear(); | ||
|  |         destroyData(); | ||
|  |     } | ||
|  | 
 | ||
|  |     gim_array() | ||
|  |     { | ||
|  |         m_data = 0; | ||
|  |         m_size = 0; | ||
|  |         m_allocated_size = 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     gim_array(GUINT reservesize) | ||
|  |     { | ||
|  |         m_data = 0; | ||
|  |         m_size = 0; | ||
|  | 
 | ||
|  |         m_allocated_size = 0; | ||
|  |         reserve(reservesize); | ||
|  |     } | ||
|  | 
 | ||
|  |     ~gim_array() | ||
|  |     { | ||
|  |         clear_memory(); | ||
|  |     } | ||
|  | 
 | ||
|  |     inline GUINT size() const | ||
|  |     { | ||
|  |         return m_size; | ||
|  |     } | ||
|  | 
 | ||
|  |     inline GUINT max_size() const | ||
|  |     { | ||
|  |         return m_allocated_size; | ||
|  |     } | ||
|  | 
 | ||
|  |     inline T & operator[](size_t i) | ||
|  | 	{ | ||
|  | 		return m_data[i]; | ||
|  | 	} | ||
|  | 	inline  const T & operator[](size_t i) const | ||
|  | 	{ | ||
|  | 		return m_data[i]; | ||
|  | 	} | ||
|  | 
 | ||
|  |     inline T * pointer(){ return m_data;} | ||
|  |     inline const T * pointer() const | ||
|  |     { return m_data;} | ||
|  | 
 | ||
|  | 
 | ||
|  |     inline T * get_pointer_at(GUINT i) | ||
|  | 	{ | ||
|  | 		return m_data + i; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline const T * get_pointer_at(GUINT i) const | ||
|  | 	{ | ||
|  | 		return m_data + i; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline T & at(GUINT i) | ||
|  | 	{ | ||
|  | 		return m_data[i]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline const T & at(GUINT i) const | ||
|  | 	{ | ||
|  | 		return m_data[i]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline T & front() | ||
|  | 	{ | ||
|  | 		return *m_data; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline const T & front() const | ||
|  | 	{ | ||
|  | 		return *m_data; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline T & back() | ||
|  | 	{ | ||
|  | 		return m_data[m_size-1]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline const T & back() const | ||
|  | 	{ | ||
|  | 		return m_data[m_size-1]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	inline void swap(GUINT i, GUINT j) | ||
|  | 	{ | ||
|  | 	    gim_swap_elements(m_data,i,j); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void push_back(const T & obj) | ||
|  | 	{ | ||
|  | 	    this->growingCheck(); | ||
|  | 	    m_data[m_size] = obj; | ||
|  | 	    m_size++; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	//!Simply increase the m_size, doesn't call the new element constructor
 | ||
|  | 	inline void push_back_mem() | ||
|  | 	{ | ||
|  | 	    this->growingCheck(); | ||
|  | 	    m_size++; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void push_back_memcpy(const T & obj) | ||
|  | 	{ | ||
|  | 	    this->growingCheck(); | ||
|  | 	    gim_simd_memcpy(&m_data[m_size],&obj,sizeof(T)); | ||
|  | 	    m_size++; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void pop_back() | ||
|  | 	{ | ||
|  | 	    m_size--; | ||
|  |         m_data[m_size].~T(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	//!Simply decrease the m_size, doesn't call the deleted element destructor
 | ||
|  | 	inline void pop_back_mem() | ||
|  | 	{ | ||
|  | 	    m_size--; | ||
|  | 	} | ||
|  | 
 | ||
|  |     //! fast erase
 | ||
|  | 	inline void erase(GUINT index) | ||
|  | 	{ | ||
|  | 	    if(index<m_size-1) | ||
|  | 	    { | ||
|  | 	        swap(index,m_size-1); | ||
|  | 	    } | ||
|  | 	    pop_back(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void erase_sorted_mem(GUINT index) | ||
|  | 	{ | ||
|  | 	    m_size--; | ||
|  | 	    for(GUINT i = index;i<m_size;i++) | ||
|  | 	    { | ||
|  | 	        gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T)); | ||
|  | 	    } | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void erase_sorted(GUINT index) | ||
|  | 	{ | ||
|  | 	    m_data[index].~T(); | ||
|  | 	    erase_sorted_mem(index); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void insert_mem(GUINT index) | ||
|  | 	{ | ||
|  | 	    this->growingCheck(); | ||
|  | 	    for(GUINT i = m_size;i>index;i--) | ||
|  | 	    { | ||
|  | 	        gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T)); | ||
|  | 	    } | ||
|  | 	    m_size++; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void insert(const T & obj,GUINT index) | ||
|  | 	{ | ||
|  | 	    insert_mem(index); | ||
|  | 	    m_data[index] = obj; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T()) | ||
|  | 	{ | ||
|  | 	    if(size>m_size) | ||
|  | 	    { | ||
|  |             reserve(size); | ||
|  |             if(call_constructor) | ||
|  |             { | ||
|  |                 while(m_size<size) | ||
|  |                 { | ||
|  |                     m_data[m_size] = fillData; | ||
|  |                     m_size++; | ||
|  |                 } | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |             	m_size = size; | ||
|  |             } | ||
|  | 	    } | ||
|  | 	    else if(size<m_size) | ||
|  | 	    { | ||
|  | 	        if(call_constructor) clear_range(size); | ||
|  | 	        m_size = size; | ||
|  | 	    } | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline void refit() | ||
|  | 	{ | ||
|  | 	    resizeData(m_size); | ||
|  | 	} | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif // GIM_CONTAINERS_H_INCLUDED
 |