Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // CContainer - A c++ templated storage class
- // Copyright (C) 2014 Erick "RetroZelda" Folckemer
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // at your option) any later version.
- //
- // This program 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
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- template<typename T>
- class CContainer
- {
- private:
- struct ObjectBlock
- {
- ObjectBlock* pNext;
- T object;
- };
- ObjectBlock* m_pListHead;
- ObjectBlock* m_pListTail;
- ObjectBlock* m_pFreeBlocks;
- ObjectBlock* m_pFreeBlocksTail;
- char* m_pDataLocation;
- unsigned m_unBufferSize;
- unsigned m_unTypeSize;
- unsigned m_unCapacity;
- unsigned m_unCount;
- void ClaimAllBlocks();
- char* GetBlockByIndex(unsigned unIndex);
- public:
- CContainer(char * pBuffer, unsigned nBufferSize); // Constructs the container from a pre-defined buffer.
- ~CContainer();
- T* Add(); // Adds an element to the container, constructs it and returns it to the caller.
- void Remove(T *); // Removes an object from the container.
- unsigned Count() const; // Number of elements currently in the container.
- unsigned Capacity() const; // Max number of elements the container can contain. You can limit the capacity to 65536 elements if this makes your implementation easier.
- bool IsEmpty() const; // Is container empty?
- bool IsFull() const; // Is container full?
- T const* operator [] (unsigned nIndex) const; // Returns the n th element of the container [0..Count -1].
- T* operator [] (unsigned nIndex); // Returns the n th element of the container [0..Count -1].
- };
- /* Private Functions */
- template<typename T>
- void CContainer<T>::ClaimAllBlocks()
- {
- // iterate through everything
- for(unsigned blockIndex = 0; blockIndex < m_unCapacity; ++blockIndex)
- {
- ObjectBlock* pCurentBlock = (ObjectBlock*)(m_pDataLocation + (blockIndex * m_unTypeSize));
- memset(pCurentBlock, 0, sizeof(ObjectBlock));
- // set the next block
- if(blockIndex < m_unCapacity - 1)
- {
- pCurentBlock->pNext = pCurentBlock + 1;
- }
- else
- {
- // the last in the list
- pCurentBlock->pNext = NULL;
- }
- }
- }
- template<typename T>
- char* CContainer<T>::GetBlockByIndex(unsigned unIndex)
- {
- // ensure we can hit the number
- if(unIndex >= m_unCount)
- {
- // guess we cant
- return NULL;
- }
- // go through the list 'unIndex' ammount of times
- // NOTE: a while() loop for less keystrokes :)
- ObjectBlock* pBlock = m_pListHead;
- while(unIndex > 0)
- {
- pBlock = pBlock->pNext;
- --unIndex;
- }
- return (char*)pBlock;
- }
- /* Public Functions */
- template<typename T>
- CContainer<T>::CContainer(char * pBuffer, unsigned nBufferSize)
- {
- // set the general data
- m_pDataLocation = pBuffer;
- m_unBufferSize = nBufferSize;
- m_unTypeSize = sizeof(ObjectBlock);
- m_unCount = 0;
- // calculate the max capacity
- m_unCapacity = m_unBufferSize / m_unTypeSize;
- // mark all blocks as free
- ClaimAllBlocks();
- // start the free list
- m_pFreeBlocks = (ObjectBlock*)(m_pDataLocation);
- m_pFreeBlocksTail = m_pFreeBlocks + m_unCapacity - 1;
- m_pListHead = NULL;
- m_pListTail = NULL;
- }
- template<typename T>
- CContainer<T>::~CContainer()
- {
- }
- template<typename T>
- T* CContainer<T>::Add()
- {
- // make sure there is room
- bool bFull = IsFull();
- if(bFull == true)
- {
- return NULL;
- }
- // get the top block and move the free head
- ObjectBlock* pBlock = m_pFreeBlocks;
- m_pFreeBlocks = m_pFreeBlocks->pNext;
- pBlock->pNext = NULL;
- // append new block to end
- ObjectBlock* pEndBlock = m_pListHead;
- if(pEndBlock == NULL)
- {
- // the first in the list
- m_pListHead = pBlock;
- m_pListTail = pBlock;
- pBlock->pNext = NULL;
- }
- else
- {
- // append to end
- m_pListTail->pNext = pBlock;
- m_pListTail = pBlock;
- }
- // call the objects contrustor
- new(&pBlock->object) T();
- ++m_unCount;
- return &pBlock->object;
- }
- template<typename T>
- void CContainer<T>::Remove(T *pObject)
- {
- // dont bother if empty
- bool bEmpty = IsEmpty();
- if(bEmpty)
- {
- return;
- }
- // find the object
- ObjectBlock* pBlock = m_pListHead;
- ObjectBlock* pPrevBlock = NULL;
- while(pBlock != NULL)
- {
- // we can leave if object is found
- if((&pBlock->object) == pObject)
- {
- break;
- }
- pPrevBlock = pBlock;
- pBlock = pBlock->pNext;
- }
- if(pBlock != NULL)
- {
- // call destructor
- (&pBlock->object)->~T();
- // remove from main list
- if(pPrevBlock == NULL)
- {
- // head of the list
- m_pListHead = pBlock->pNext;
- }
- else
- {
- // remove
- pPrevBlock->pNext = pBlock->pNext;
- }
- // add to end of free list
- pBlock->pNext = NULL;
- if(m_pFreeBlocks == NULL)
- {
- // free list empty
- // NOTE: could also use IsFull()
- m_pFreeBlocks = pBlock;
- m_pFreeBlocksTail = pBlock;
- }
- else
- {
- // add to end
- m_pFreeBlocksTail->pNext = pBlock;
- m_pFreeBlocksTail = pBlock;
- }
- // subtract count
- --m_unCount;
- }
- }
- template<typename T>
- unsigned CContainer<T>::Count() const
- {
- return m_unCount;
- }
- template<typename T>
- unsigned CContainer<T>::Capacity() const
- {
- return m_unCapacity;
- }
- template<typename T>
- bool CContainer<T>::IsEmpty() const
- {
- return (m_unCount == 0);
- }
- template<typename T>
- bool CContainer<T>::IsFull() const
- {
- return (m_unCount == m_unCapacity);
- }
- template<typename T>
- T const* CContainer<T>::operator [] (unsigned nIndex) const
- {
- return this[nIndex];
- }
- template<typename T>
- T* CContainer<T>::operator [] (unsigned nIndex)
- {
- ObjectBlock* pBlock = (ObjectBlock*)GetBlockByIndex(nIndex);
- if(pBlock != NULL)
- {
- return &pBlock->object;
- }
- // we are here if a bad index was given
- return NULL;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement