Created
April 8, 2010 02:01
-
-
Save zachelko/359698 to your computer and use it in GitHub Desktop.
Templated list data structure that enables you to toggle 'wrap-around' functionality to achieve a circular list.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CircularList.hpp | |
// | |
// Zach Elko | |
// 2010 | |
// | |
// Simple templated data structure that allows you to toggle 'wrap-around' behavior | |
// to achieve a circular list. | |
// | |
#ifndef CIRCULAR_LIST_H | |
#define CIRCULAR_LIST_H | |
#include <list> | |
#include <iostream> | |
template <typename T> | |
class CircularList | |
{ | |
public: | |
CircularList(const bool wrapAround) : | |
m_bWrapAround(wrapAround) | |
{ | |
m_iteratorCurrent = m_listItems.end(); | |
m_pCurrentItem = 0; | |
} | |
void setWrapEnabled(const bool wrapAround) | |
{ | |
m_bWrapAround = wrapAround; | |
} | |
bool isWrapEnabled() | |
{ | |
return m_bWrapAround; | |
} | |
void addItem(const T* const item) | |
{ | |
m_listItems.push_back(*item); | |
// This was the first item added, so we can set | |
// our current iterator to begin() | |
// TODO: This is kind of kludgy... | |
if (m_pCurrentItem == 0) | |
{ | |
m_iteratorCurrent = m_listItems.begin(); | |
} | |
m_pCurrentItem = &(*m_iteratorCurrent); | |
} | |
T* nextItem() | |
{ | |
if (!m_listItems.empty()) | |
{ | |
if (m_bWrapAround) | |
{ | |
// If we are at the last item in the list, wrap to the front | |
if (*m_iteratorCurrent == m_listItems.back()) | |
{ | |
m_iteratorCurrent = m_listItems.begin(); | |
} | |
else | |
{ | |
++m_iteratorCurrent; | |
} | |
} | |
else | |
{ | |
// Only increment if we aren't at the last element already | |
if (*m_iteratorCurrent != m_listItems.back()) | |
{ | |
++m_iteratorCurrent; | |
} | |
} | |
m_pCurrentItem = &(*m_iteratorCurrent); | |
return m_pCurrentItem; | |
} | |
return 0; | |
} | |
T* prevItem() | |
{ | |
if (!m_listItems.empty()) | |
{ | |
// If we are at the front and want to move back, | |
// only do so if wrapping is enabled. | |
if (m_iteratorCurrent == m_listItems.begin()) | |
{ | |
if (m_bWrapAround) | |
{ | |
*m_iteratorCurrent = m_listItems.back(); | |
} | |
} | |
else | |
{ | |
// Otherwise, move back. | |
--m_iteratorCurrent; | |
} | |
m_pCurrentItem = &(*m_iteratorCurrent); | |
return m_pCurrentItem; | |
} | |
return 0; | |
} | |
void removeCurrentItem() | |
{ | |
if (!m_listItems.empty()) | |
{ | |
if (m_listItems.size() == 1) | |
{ | |
removeAllItems(); | |
} | |
else | |
{ | |
if (*m_iteratorCurrent == m_listItems.back()) | |
{ | |
// If we remove the last element, remain at the end by | |
// moving to the old next-to-last element | |
m_listItems.erase(m_iteratorCurrent--); | |
} | |
else | |
{ | |
// Otherwise, move to the next one | |
m_listItems.erase(m_iteratorCurrent++); | |
} | |
m_pCurrentItem = &(*m_iteratorCurrent); | |
} | |
} | |
} | |
void removeAllItems() | |
{ | |
if (!m_listItems.empty()) | |
{ | |
m_listItems.clear(); | |
m_iteratorCurrent = m_listItems.end(); | |
m_pCurrentItem = 0; | |
} | |
} | |
T* currItem() | |
{ | |
return m_pCurrentItem; | |
} | |
private: | |
bool m_bWrapAround; | |
std::list<T> m_listItems; | |
T* m_pCurrentItem; | |
typename std::list<T>::iterator m_iteratorCurrent; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment