Advertisement
RetroZelda

C++ Templated Container

Mar 24th, 2016
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.79 KB | None | 0 0
  1. // CContainer - A c++ templated storage class
  2. // Copyright (C) 2014  Erick "RetroZelda" Folckemer
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16.  
  17. template<typename T>
  18. class CContainer
  19. {
  20. private:
  21.     struct ObjectBlock
  22.     {
  23.         ObjectBlock* pNext;
  24.         T object;
  25.     };
  26.     ObjectBlock* m_pListHead;
  27.     ObjectBlock* m_pListTail;
  28.     ObjectBlock* m_pFreeBlocks;
  29.     ObjectBlock* m_pFreeBlocksTail;
  30.     char*       m_pDataLocation;
  31.     unsigned    m_unBufferSize;
  32.     unsigned    m_unTypeSize;
  33.     unsigned    m_unCapacity;
  34.     unsigned    m_unCount;
  35.  
  36.     void  ClaimAllBlocks();
  37.     char* GetBlockByIndex(unsigned unIndex);
  38. public:
  39.     CContainer(char * pBuffer, unsigned nBufferSize); // Constructs the container from a pre-defined buffer.
  40.     ~CContainer();
  41.  
  42.     T* Add(); // Adds an element to the container, constructs it and returns it to the caller.
  43.     void Remove(T *); // Removes an object from the container.
  44.  
  45.     unsigned Count() const; // Number of elements currently in the container.
  46.     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.
  47.  
  48.     bool IsEmpty() const; // Is container empty?
  49.     bool IsFull() const; // Is container full?
  50.  
  51.     T const* operator [] (unsigned nIndex) const; // Returns the n th element of the container [0..Count -1].
  52.     T* operator [] (unsigned nIndex); // Returns the n th element of the container [0..Count -1].
  53.  
  54. };
  55.  
  56. /* Private Functions */
  57.  
  58. template<typename T>
  59. void CContainer<T>::ClaimAllBlocks()
  60. {
  61.     // iterate through everything
  62.     for(unsigned blockIndex = 0; blockIndex < m_unCapacity; ++blockIndex)
  63.     {
  64.         ObjectBlock* pCurentBlock = (ObjectBlock*)(m_pDataLocation + (blockIndex * m_unTypeSize));
  65.         memset(pCurentBlock, 0, sizeof(ObjectBlock));
  66.  
  67.         // set the next block
  68.         if(blockIndex < m_unCapacity - 1)
  69.         {
  70.             pCurentBlock->pNext = pCurentBlock + 1;
  71.         }
  72.         else
  73.         {
  74.             // the last in the list
  75.             pCurentBlock->pNext = NULL;
  76.         }
  77.     }
  78. }
  79.  
  80. template<typename T>
  81. char* CContainer<T>::GetBlockByIndex(unsigned unIndex)
  82. {
  83.     // ensure we can hit the number
  84.     if(unIndex >= m_unCount)
  85.     {
  86.         // guess we cant
  87.         return NULL;
  88.     }
  89.  
  90.     // go through the list 'unIndex' ammount of times
  91.     // NOTE: a while() loop for less keystrokes :)
  92.     ObjectBlock* pBlock = m_pListHead;
  93.     while(unIndex > 0)
  94.     {
  95.         pBlock = pBlock->pNext;
  96.         --unIndex;
  97.     }
  98.  
  99.     return (char*)pBlock;
  100. }
  101.  
  102. /* Public Functions */
  103. template<typename T>
  104. CContainer<T>::CContainer(char * pBuffer, unsigned nBufferSize)
  105. {
  106.     // set the general data
  107.     m_pDataLocation = pBuffer;
  108.     m_unBufferSize = nBufferSize;
  109.     m_unTypeSize = sizeof(ObjectBlock);
  110.     m_unCount = 0;
  111.  
  112.     // calculate the max capacity
  113.     m_unCapacity = m_unBufferSize / m_unTypeSize;
  114.  
  115.     // mark all blocks as free
  116.     ClaimAllBlocks();
  117.  
  118.     // start the free list
  119.     m_pFreeBlocks = (ObjectBlock*)(m_pDataLocation);
  120.     m_pFreeBlocksTail = m_pFreeBlocks + m_unCapacity - 1;
  121.     m_pListHead = NULL;
  122.     m_pListTail = NULL;
  123. }
  124.  
  125. template<typename T>
  126. CContainer<T>::~CContainer()
  127. {
  128. }
  129.  
  130. template<typename T>
  131. T* CContainer<T>::Add()
  132. {
  133.     // make sure there is room
  134.     bool bFull = IsFull();
  135.     if(bFull == true)
  136.     {
  137.         return NULL;
  138.     }
  139.  
  140.     // get the top block and move the free head
  141.     ObjectBlock* pBlock = m_pFreeBlocks;
  142.     m_pFreeBlocks = m_pFreeBlocks->pNext;
  143.     pBlock->pNext = NULL;
  144.  
  145.     // append new block to end
  146.     ObjectBlock* pEndBlock = m_pListHead;
  147.     if(pEndBlock == NULL)
  148.     {
  149.         // the first in the list
  150.         m_pListHead = pBlock;
  151.         m_pListTail = pBlock;
  152.         pBlock->pNext = NULL;
  153.     }
  154.     else
  155.     {
  156.         // append to end
  157.         m_pListTail->pNext = pBlock;
  158.         m_pListTail = pBlock;
  159.     }
  160.  
  161.     // call the objects contrustor
  162.     new(&pBlock->object) T();
  163.     ++m_unCount;
  164.  
  165.     return &pBlock->object;
  166. }
  167.  
  168. template<typename T>
  169. void CContainer<T>::Remove(T *pObject)
  170. {
  171.     // dont bother if empty
  172.     bool bEmpty = IsEmpty();
  173.     if(bEmpty)
  174.     {
  175.         return;
  176.     }
  177.  
  178.     // find the object
  179.     ObjectBlock* pBlock = m_pListHead;
  180.     ObjectBlock* pPrevBlock = NULL;
  181.     while(pBlock != NULL)
  182.     {
  183.         // we can leave if object is found
  184.         if((&pBlock->object) == pObject)
  185.         {
  186.             break;
  187.         }
  188.         pPrevBlock = pBlock;
  189.         pBlock = pBlock->pNext;
  190.     }
  191.  
  192.     if(pBlock != NULL)
  193.     {
  194.         // call destructor
  195.         (&pBlock->object)->~T();
  196.  
  197.         // remove from main list
  198.         if(pPrevBlock == NULL)
  199.         {
  200.             // head of the list
  201.             m_pListHead = pBlock->pNext;
  202.         }
  203.         else
  204.         {
  205.             // remove
  206.             pPrevBlock->pNext = pBlock->pNext;
  207.         }
  208.  
  209.         // add to end of free list
  210.         pBlock->pNext = NULL;
  211.         if(m_pFreeBlocks == NULL)
  212.         {
  213.             // free list empty
  214.             // NOTE: could also use IsFull()
  215.             m_pFreeBlocks = pBlock;
  216.             m_pFreeBlocksTail = pBlock;
  217.         }
  218.         else
  219.         {
  220.             // add to end
  221.             m_pFreeBlocksTail->pNext = pBlock;
  222.             m_pFreeBlocksTail = pBlock;
  223.         }
  224.  
  225.         // subtract count
  226.         --m_unCount;
  227.     }
  228. }
  229.  
  230. template<typename T>
  231. unsigned CContainer<T>::Count() const
  232. {
  233.     return m_unCount;
  234. }
  235.  
  236. template<typename T>
  237. unsigned CContainer<T>::Capacity() const
  238. {
  239.     return m_unCapacity;
  240. }
  241.  
  242.  
  243. template<typename T>
  244. bool CContainer<T>::IsEmpty() const
  245. {
  246.     return (m_unCount == 0);
  247. }
  248.  
  249. template<typename T>
  250. bool CContainer<T>::IsFull() const
  251. {
  252.  
  253.     return (m_unCount == m_unCapacity);
  254. }
  255.  
  256.  
  257. template<typename T>
  258. T const* CContainer<T>::operator [] (unsigned nIndex) const
  259. {
  260.     return this[nIndex];
  261. }
  262.  
  263. template<typename T>
  264. T* CContainer<T>::operator [] (unsigned nIndex)
  265. {
  266.     ObjectBlock* pBlock = (ObjectBlock*)GetBlockByIndex(nIndex);
  267.  
  268.     if(pBlock != NULL)
  269.     {
  270.         return &pBlock->object;
  271.     }
  272.  
  273.     // we are here if a bad index was given
  274.     return NULL;
  275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement