/******************************************************************************* Copyright (c) 2005-2009 David Williams This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. *******************************************************************************/ namespace PolyVox { //////////////////////////////////////////////////////////////////////////////// /// Creates an empty array with no elements. You will have to call resize() on this /// array before it can be used. //////////////////////////////////////////////////////////////////////////////// template Array::Array() :m_pElements(0) ,m_pDimensions(0) ,m_pOffsets(0) ,m_uNoOfElements(0) { } //////////////////////////////////////////////////////////////////////////////// /// Creates an array with the specified dimensions. /// \param pDimensions The dimensions of the array. You can also use the ArraySizes /// class to construct this more easily. /// \sa ArraySizes //////////////////////////////////////////////////////////////////////////////// template Array::Array(const uint32_t (&pDimensions)[noOfDims]) :m_pElements(0) ,m_pDimensions(0) ,m_pOffsets(0) ,m_uNoOfElements(0) { resize(pDimensions); } //////////////////////////////////////////////////////////////////////////////// /// Destroys the array and releases all owned memory. //////////////////////////////////////////////////////////////////////////////// template Array::~Array() { deallocate(); } //////////////////////////////////////////////////////////////////////////////// /// An N-dimensional array can be conceptually consists of N subarrays each of which /// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D /// arrays. This operator is used to access the subarray at the specified index. /// Crucially, the subarray defines a similar operator allowing them to be chained /// together to convieniently access a particular element. /// \param uIndex The zero-based index of the subarray to retrieve. /// \return The requested SubArray //////////////////////////////////////////////////////////////////////////////// template SubArray Array::operator[](uint32_t uIndex) { assert(uIndex(&m_pElements[uIndex*m_pOffsets[0]], m_pDimensions+1, m_pOffsets+1); } //////////////////////////////////////////////////////////////////////////////// /// An N-dimensional array can be conceptually consists of N subarrays each of which /// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D /// arrays. This operator is used to access the subarray at the specified index. /// Crucially, the subarray defines a similar operator allowing them to be chained /// together to convieniently access a particular element. /// \param uIndex The zero-based index of the subarray to retrieve. /// \return The requested SubArray //////////////////////////////////////////////////////////////////////////////// template const SubArray Array::operator[](uint32_t uIndex) const { assert(uIndex(&m_pElements[uIndex*m_pOffsets[0]], m_pDimensions+1, m_pOffsets+1); } //////////////////////////////////////////////////////////////////////////////// /// \return The number of elements in the array. /// \sa getRawData() //////////////////////////////////////////////////////////////////////////////// template uint32_t Array::getNoOfElements(void) const { return m_uNoOfElements; } //////////////////////////////////////////////////////////////////////////////// /// Sometimes it is useful to directly manipulate the underlying array without /// going through this classes interface. Although this does not honour the principle /// of encapsulation it can be done safely if you are careful and can sometimes be /// useful. Use getNoOfElements() to determine how far you can safely write. /// \return A pointer to the first element of the array /// \sa getNoOfElements() //////////////////////////////////////////////////////////////////////////////// template ElementType* Array::getRawData(void) const { return m_pElements; } //////////////////////////////////////////////////////////////////////////////// /// Please note that the existing contents of the array will be lost. /// \param pDimensions The new dimensions of the array. You can also use the /// ArraySizes class to specify this more easily. /// \sa ArraySizes //////////////////////////////////////////////////////////////////////////////// template void Array::resize(const uint32_t (&pDimensions)[noOfDims]) { deallocate(); m_pDimensions = new uint32_t[noOfDims]; m_pOffsets = new uint32_t[noOfDims]; // Calculate all the information you need to use the array m_uNoOfElements = 1; for (uint32_t i = 0; ii; k--) { m_pOffsets[i] *= pDimensions[k]; } } // Allocate new elements, let exception propagate m_pElements = new ElementType[m_uNoOfElements]; } //////////////////////////////////////////////////////////////////////////////// /// Because this class does not have a public assignment operator or copy constructor /// it cnnot be used with the STL swap() function. This function provides an efficient /// implementation of that feature. /// \param rhs The array to swap this object with. //////////////////////////////////////////////////////////////////////////////// template void Array::swap(Array& rhs) { //Implement this function without temporary 'Array' //objects, as the destructors will free the memory... uint32_t* m_pTempDimensions = m_pDimensions; uint32_t* m_pTempOffsets = m_pOffsets; uint32_t m_uTempNoOfElements = m_uNoOfElements; ElementType* m_pTempElements = m_pElements; m_pDimensions = rhs.m_pDimensions; m_pOffsets = rhs.m_pOffsets; m_uNoOfElements = rhs.m_uNoOfElements; m_pElements = rhs.m_pElements; rhs.m_pDimensions = m_pTempDimensions; rhs.m_pOffsets = m_pTempOffsets; rhs.m_uNoOfElements = m_uTempNoOfElements; rhs.m_pElements = m_pTempElements; } template Array::Array(const Array& rhs) :m_pElements(0) ,m_pDimensions(0) ,m_pOffsets(0) ,m_uNoOfElements(0) { //Not implemented assert(false); } template Array& Array::operator=(const Array& rhs) { //Not implemented assert(false); return *this; } template void Array::deallocate(void) { delete[] m_pDimensions; m_pDimensions = 0; delete[] m_pOffsets; m_pOffsets = 0; delete[] m_pElements; m_pElements = 0; m_uNoOfElements = 0; } //****************************************************************************// // One dimensional specialisation begins here // //****************************************************************************// template Array<1, ElementType>::Array() : m_pElements(0) ,m_pDimensions(0) { } template Array<1, ElementType>::Array(const uint32_t (&pDimensions)[1]) : m_pElements(0) ,m_pDimensions(0) { resize(pDimensions); } template Array<1, ElementType>::~Array() { deallocate(); } template ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) { assert(uIndex const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const { assert(uIndex uint32_t Array<1, ElementType>::getNoOfElements(void) const { return m_pDimensions[0]; } template ElementType* Array<1, ElementType>::getRawData(void) const { return m_pElements; } template void Array<1, ElementType>::resize(const uint32_t (&pDimensions)[1]) { deallocate(); m_pDimensions = new uint32_t[1]; m_pDimensions[0] = pDimensions[0]; // Allocate new elements, let exception propagate m_pElements = new ElementType[m_pDimensions[0]]; } template void Array<1, ElementType>::swap(Array<1, ElementType>& rhs) { //Implement this function without temporary 'Array' //objects, as the destructors will free the memory... uint32_t* m_pTempDimensions = m_pDimensions; ElementType* m_pTempElements = m_pElements; m_pDimensions = rhs.m_pDimensions; m_pElements = rhs.m_pElements; rhs.m_pDimensions = m_pTempDimensions; rhs.m_pElements = m_pTempElements; } template Array<1, ElementType>::Array(const Array<1, ElementType>& rhs) : m_pElements(0) ,m_pDimensions(0) { //Not implemented assert(false); } template Array<1, ElementType>& Array<1, ElementType>::operator=(const Array<1, ElementType>& rhs) { //Not implemented assert(false); return *this; } template void Array<1, ElementType>::deallocate(void) { delete[] m_pDimensions; m_pDimensions = 0; delete[] m_pElements; m_pElements = 0; } }//namespace PolyVox