Skip to content

Instantly share code, notes, and snippets.

@zachelko
Created April 8, 2010 02:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zachelko/359698 to your computer and use it in GitHub Desktop.
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.
// 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