| #ifndef _DEARRAYBUFFER_HPP | 
 | #define _DEARRAYBUFFER_HPP | 
 | /*------------------------------------------------------------------------- | 
 |  * drawElements C++ Base Library | 
 |  * ----------------------------- | 
 |  * | 
 |  * Copyright 2014 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  * | 
 |  *//*! | 
 |  * \file | 
 |  * \brief Array buffer | 
 |  *//*--------------------------------------------------------------------*/ | 
 |  | 
 | #include "deDefs.hpp" | 
 | #include "deMemory.h" | 
 |  | 
 | #include <new> | 
 |  | 
 | namespace de | 
 | { | 
 | namespace detail | 
 | { | 
 |  | 
 | void* ArrayBuffer_AlignedMalloc (size_t numBytes, size_t alignment); | 
 | void ArrayBuffer_AlignedFree (void*); | 
 |  | 
 | } // detail | 
 |  | 
 | //! Array buffer self-test. | 
 | void ArrayBuffer_selfTest (void); | 
 |  | 
 | /*--------------------------------------------------------------------*//*! | 
 |  * \brief Contiguous array that does not initialize its elements. | 
 |  *//*--------------------------------------------------------------------*/ | 
 | template <typename T, size_t Alignment = (sizeof(T) > 4 ? 4 : sizeof(T)), size_t Stride = sizeof(T)> | 
 | class ArrayBuffer | 
 | { | 
 | public: | 
 | 	DE_STATIC_ASSERT(Stride >= sizeof(T)); | 
 |  | 
 | 					ArrayBuffer		(void) throw(); | 
 | 					ArrayBuffer		(size_t numElements); | 
 | 					ArrayBuffer		(const T* ptr, size_t numElements); | 
 | 					ArrayBuffer		(const ArrayBuffer& other); | 
 | 					~ArrayBuffer	(void) throw(); | 
 | 	ArrayBuffer&	operator=		(const ArrayBuffer& other); | 
 |  | 
 | 	void			clear			(void) throw(); | 
 | 	void			setStorage		(size_t numElements); // !< \note after a succesful call buffer contents are undefined | 
 | 	void			swap			(ArrayBuffer& other) throw(); | 
 | 	size_t			size			(void) const throw(); | 
 | 	bool			empty			(void) const throw(); | 
 |  | 
 | 	T*				getElementPtr	(size_t elementNdx) throw(); | 
 | 	const T*		getElementPtr	(size_t elementNdx) const throw(); | 
 | 	void*			getPtr			(void) throw(); | 
 | 	const void*		getPtr			(void) const throw(); | 
 |  | 
 | private: | 
 | 	void*			m_ptr; | 
 | 	size_t			m_cap; | 
 | } DE_WARN_UNUSED_TYPE; | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (void) throw() | 
 | 	: m_ptr	(DE_NULL) | 
 | 	, m_cap	(0) | 
 | { | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (size_t numElements) | 
 | 	: m_ptr	(DE_NULL) | 
 | 	, m_cap	(0) | 
 | { | 
 | 	if (numElements) | 
 | 	{ | 
 | 		// \note no need to allocate stride for the last element, sizeof(T) is enough. Also handles cases where sizeof(T) > Stride | 
 | 		const size_t	storageSize	= (numElements - 1) * Stride + sizeof(T); | 
 | 		void* const		ptr			= detail::ArrayBuffer_AlignedMalloc(storageSize, Alignment); | 
 |  | 
 | 		if (!ptr) | 
 | 			throw std::bad_alloc(); | 
 |  | 
 | 		m_ptr = ptr; | 
 | 		m_cap = numElements; | 
 | 	} | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const T* ptr, size_t numElements) | 
 | 	: m_ptr	(DE_NULL) | 
 | 	, m_cap	(0) | 
 | { | 
 | 	if (numElements) | 
 | 	{ | 
 | 		// create new buffer of wanted size, copy to it, and swap to it | 
 | 		ArrayBuffer<T,Alignment,Stride> tmp(numElements); | 
 |  | 
 | 		if (Stride == sizeof(T)) | 
 | 		{ | 
 | 			// tightly packed | 
 | 			const size_t storageSize = sizeof(T) * numElements; | 
 | 			deMemcpy(tmp.m_ptr, ptr, (int)storageSize); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			// sparsely packed | 
 | 			for (size_t ndx = 0; ndx < numElements; ++ndx) | 
 | 				*tmp.getElementPtr(ndx) = ptr[ndx]; | 
 | 		} | 
 |  | 
 | 		swap(tmp); | 
 | 	} | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const ArrayBuffer<T,Alignment,Stride>& other) | 
 | 	: m_ptr	(DE_NULL) | 
 | 	, m_cap	(0) | 
 | { | 
 | 	if (other.m_cap) | 
 | 	{ | 
 | 		// copy to temporary and swap to it | 
 |  | 
 | 		const size_t	storageSize =	(other.m_cap - 1) * Stride + sizeof(T); | 
 | 		ArrayBuffer		tmp				(other.m_cap); | 
 |  | 
 | 		deMemcpy(tmp.m_ptr, other.m_ptr, (int)storageSize); | 
 | 		swap(tmp); | 
 | 	} | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>::~ArrayBuffer (void) throw() | 
 | { | 
 | 	clear(); | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | ArrayBuffer<T,Alignment,Stride>& ArrayBuffer<T,Alignment,Stride>::operator= (const ArrayBuffer& other) | 
 | { | 
 | 	ArrayBuffer copied(other); | 
 | 	swap(copied); | 
 | 	return *this; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | void ArrayBuffer<T,Alignment,Stride>::clear (void) throw() | 
 | { | 
 | 	detail::ArrayBuffer_AlignedFree(m_ptr); | 
 |  | 
 | 	m_ptr = DE_NULL; | 
 | 	m_cap = 0; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | void ArrayBuffer<T,Alignment,Stride>::setStorage (size_t numElements) | 
 | { | 
 | 	// create new buffer of the wanted size, swap to it | 
 | 	ArrayBuffer<T,Alignment,Stride> newBuffer(numElements); | 
 | 	swap(newBuffer); | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | void ArrayBuffer<T,Alignment,Stride>::swap (ArrayBuffer& other) throw() | 
 | { | 
 | 	void* const		otherPtr = other.m_ptr; | 
 | 	const size_t	otherCap = other.m_cap; | 
 |  | 
 | 	other.m_ptr = m_ptr; | 
 | 	other.m_cap = m_cap; | 
 | 	m_ptr		= otherPtr; | 
 | 	m_cap		= otherCap; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | size_t ArrayBuffer<T,Alignment,Stride>::size (void) const throw() | 
 | { | 
 | 	return m_cap; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | bool ArrayBuffer<T,Alignment,Stride>::empty (void) const throw() | 
 | { | 
 | 	return size() == 0; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) throw() | 
 | { | 
 | 	return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | const T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) const throw() | 
 | { | 
 | 	return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) throw() | 
 | { | 
 | 	return m_ptr; | 
 | } | 
 |  | 
 | template <typename T, size_t Alignment, size_t Stride> | 
 | const void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) const throw() | 
 | { | 
 | 	return m_ptr; | 
 | } | 
 |  | 
 | } // de | 
 |  | 
 | #endif // _DEARRAYBUFFER_HPP |