Home | History | Annotate | Download | only in decpp
      1 #ifndef _DEARRAYBUFFER_HPP
      2 #define _DEARRAYBUFFER_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements C++ Base Library
      5  * -----------------------------
      6  *
      7  * Copyright 2014 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Array buffer
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "deDefs.hpp"
     27 #include "deMemory.h"
     28 
     29 #include <new>
     30 
     31 namespace de
     32 {
     33 namespace detail
     34 {
     35 
     36 void* ArrayBuffer_AlignedMalloc (size_t numBytes, size_t alignment);
     37 void ArrayBuffer_AlignedFree (void*);
     38 
     39 } // detail
     40 
     41 //! Array buffer self-test.
     42 void ArrayBuffer_selfTest (void);
     43 
     44 /*--------------------------------------------------------------------*//*!
     45  * \brief Contiguous array that does not initialize its elements.
     46  *//*--------------------------------------------------------------------*/
     47 template <typename T, size_t Alignment = (sizeof(T) > 4 ? 4 : sizeof(T)), size_t Stride = sizeof(T)>
     48 class ArrayBuffer
     49 {
     50 public:
     51 					ArrayBuffer		(void) throw();
     52 					ArrayBuffer		(size_t numElements);
     53 					ArrayBuffer		(const ArrayBuffer& other);
     54 					~ArrayBuffer	(void) throw();
     55 	ArrayBuffer&	operator=		(const ArrayBuffer& other);
     56 
     57 	void			clear			(void) throw();
     58 	void			setStorage		(size_t numElements); // !< \note after a succesful call buffer contents are undefined
     59 	void			swap			(ArrayBuffer& other) throw();
     60 	size_t			size			(void) const throw();
     61 	bool			empty			(void) const throw();
     62 
     63 	T*				getElementPtr	(size_t elementNdx) throw();
     64 	const T*		getElementPtr	(size_t elementNdx) const throw();
     65 	void*			getPtr			(void) throw();
     66 	const void*		getPtr			(void) const throw();
     67 
     68 private:
     69 	void*			m_ptr;
     70 	size_t			m_cap;
     71 };
     72 
     73 template <typename T, size_t Alignment, size_t Stride>
     74 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (void) throw()
     75 	: m_ptr	(DE_NULL)
     76 	, m_cap	(0)
     77 {
     78 }
     79 
     80 template <typename T, size_t Alignment, size_t Stride>
     81 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (size_t numElements)
     82 	: m_ptr	(DE_NULL)
     83 	, m_cap	(0)
     84 {
     85 	if (numElements)
     86 	{
     87 		// \note no need to allocate stride for the last element, sizeof(T) is enough. Also handles cases where sizeof(T) > Stride
     88 		const size_t	storageSize	= (numElements - 1) * Stride + sizeof(T);
     89 		void* const		ptr			= detail::ArrayBuffer_AlignedMalloc(storageSize, Alignment);
     90 
     91 		if (!ptr)
     92 			throw std::bad_alloc();
     93 
     94 		m_ptr = ptr;
     95 		m_cap = numElements;
     96 	}
     97 }
     98 
     99 template <typename T, size_t Alignment, size_t Stride>
    100 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const ArrayBuffer<T,Alignment,Stride>& other)
    101 	: m_ptr	(DE_NULL)
    102 	, m_cap	(0)
    103 {
    104 	if (other.m_cap)
    105 	{
    106 		// copy to temporary and swap to it
    107 
    108 		const size_t	storageSize =	(other.m_cap - 1) * Stride + sizeof(T);
    109 		ArrayBuffer		tmp				(other.m_cap);
    110 
    111 		deMemcpy(tmp.m_ptr, other.m_ptr, (int)storageSize);
    112 		swap(tmp);
    113 	}
    114 }
    115 
    116 template <typename T, size_t Alignment, size_t Stride>
    117 ArrayBuffer<T,Alignment,Stride>::~ArrayBuffer (void) throw()
    118 {
    119 	clear();
    120 }
    121 
    122 template <typename T, size_t Alignment, size_t Stride>
    123 ArrayBuffer<T,Alignment,Stride>& ArrayBuffer<T,Alignment,Stride>::operator= (const ArrayBuffer& other)
    124 {
    125 	ArrayBuffer copied(other);
    126 	swap(copied);
    127 	return *this;
    128 }
    129 
    130 template <typename T, size_t Alignment, size_t Stride>
    131 void ArrayBuffer<T,Alignment,Stride>::clear (void) throw()
    132 {
    133 	detail::ArrayBuffer_AlignedFree(m_ptr);
    134 
    135 	m_ptr = DE_NULL;
    136 	m_cap = 0;
    137 }
    138 
    139 template <typename T, size_t Alignment, size_t Stride>
    140 void ArrayBuffer<T,Alignment,Stride>::setStorage (size_t numElements)
    141 {
    142 	// create new buffer of the wanted size, swap to it
    143 	ArrayBuffer<T,Alignment,Stride> newBuffer(numElements);
    144 	swap(newBuffer);
    145 }
    146 
    147 template <typename T, size_t Alignment, size_t Stride>
    148 void ArrayBuffer<T,Alignment,Stride>::swap (ArrayBuffer& other) throw()
    149 {
    150 	void* const		otherPtr = other.m_ptr;
    151 	const size_t	otherCap = other.m_cap;
    152 
    153 	other.m_ptr = m_ptr;
    154 	other.m_cap = m_cap;
    155 	m_ptr		= otherPtr;
    156 	m_cap		= otherCap;
    157 }
    158 
    159 template <typename T, size_t Alignment, size_t Stride>
    160 size_t ArrayBuffer<T,Alignment,Stride>::size (void) const throw()
    161 {
    162 	return m_cap;
    163 }
    164 
    165 template <typename T, size_t Alignment, size_t Stride>
    166 bool ArrayBuffer<T,Alignment,Stride>::empty (void) const throw()
    167 {
    168 	return size() == 0;
    169 }
    170 
    171 template <typename T, size_t Alignment, size_t Stride>
    172 T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) throw()
    173 {
    174 	return (T*)(((deUint8*)m_ptr) + Stride * elementNdx);
    175 }
    176 
    177 template <typename T, size_t Alignment, size_t Stride>
    178 const T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) const throw()
    179 {
    180 	return (T*)(((deUint8*)m_ptr) + Stride * elementNdx);
    181 }
    182 
    183 template <typename T, size_t Alignment, size_t Stride>
    184 void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) throw()
    185 {
    186 	return m_ptr;
    187 }
    188 
    189 template <typename T, size_t Alignment, size_t Stride>
    190 const void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) const throw()
    191 {
    192 	return m_ptr;
    193 }
    194 
    195 } // de
    196 
    197 #endif // _DEARRAYBUFFER_HPP
    198