/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * 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 2, 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 GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "kryList.h" #include "kryListIterator.h" /* * Forward-only Iterator used for traversing a kryList. * * After the Iterator is initialized, the following two operations are not permitted: * * The iterator should be obtained by invoking the GetItarator method of the kryList class. * * The list on which the iterator is operating must exist as long as the iterator does. * * Just like kryList, kryListIterator can only be used for pointer types. * */ /* * Creates an iterator that is not set to anything. */ template kryListIterator::kryListIterator() : m_ptr(NULL), m_ptr_next(NULL), m_list(NULL), m_invalid(TRUE), m_allow_remove_current(FALSE) { } /* * Destroys the iterator. */ template kryListIterator::~kryListIterator() { if(this->m_list) { this->DisconnectFromList(); } } /* * If the option is enabled and the item pointed to by the iterator is removed from the list * the iterator will not be invalidated. */ template void kryListIterator::AllowRemoveCurrent() { this->m_allow_remove_current = TRUE; } /* * Checks if the list has been altered since the iterator was obtained. */ template void kryListIterator::Validate() { if(!this->m_list) { g_warning("Attempt to validate uninitialized kryListIterator"); return; } if(this->m_invalid) g_warning("Attempt to use invalidated kryListIterator"); } /*template int kryListIterator::HasData() { Validate(); return (m_ptr_next != NULL); }*/ /* * Returns the next item in the list. * * First time it is called, returns the first item in the list. * * Returns NULL if there are no more items. */ template T kryListIterator::GetNext() { Validate(); m_ptr = m_ptr_next; /* store pointer to next node so that the current node can be removed w/o invalidating the iterator */ if(m_ptr_next != NULL) { m_ptr_next = m_ptr_next->next; } if(m_ptr) { return m_ptr->data; } else { this->DisconnectFromList(); this->Invalidate(); return 0; } } /* * Removes the current item from the list. */ template void kryListIterator::Remove() { Validate(); if(!this->m_ptr) { g_warning("Attempt to remove from an uninitialized iterator."); return; } gboolean allow_prev = this->m_allow_remove_current; this->m_allow_remove_current = TRUE; this->m_list->Remove(this->m_ptr); this->m_ptr = NULL; this->m_allow_remove_current = allow_prev; } /* * Returns the data in the current position in the iterator. */ template T kryListIterator::GetData() { Validate(); if(!m_ptr) { g_warning("Attempting to retrieve data from an unitialized iterator"); return 0; } return m_ptr->data; } /* * * Sets the data in the current position in the iterator. */ template void kryListIterator::SetData(T data) { Validate(); if(!this->m_ptr) { g_warning("Setting data on an uninitialized iterator."); return; } this->m_ptr->data = data; } /* * Adds an item to the list immediately before the current item. */ template void kryListIterator::InsertBefore(T data) { Validate(); if(!this->m_ptr) { g_warning("Attempting to insert data using an uninitialized iterator."); return; } struct kryListNode *node_new = new kryListNode; node_new->data = data; node_new->next = m_ptr; if(this->m_ptr == this->m_list->m_head) { this->m_list->m_head = node_new; node_new->prev = NULL; } else { node_new->prev = this->m_ptr->prev; this->m_ptr->prev->next = node_new; } this->m_ptr->prev = node_new; this->m_list->m_length++; } /* * Sets the list over which the Iterator iterates. * The iterator is initialized to point to the first item in the list. */ template void kryListIterator::SetList(kryList *list) { if(this->m_list) this->DisconnectFromList(); if(!list) { g_warning("Attempting to initialize iterator with an empty list."); this->m_list = NULL; this->m_ptr = NULL; this->m_ptr_next = NULL; return; } this->m_list = list; this->m_ptr = list->m_head; this->m_ptr_next = list->m_head; this->m_invalid = FALSE; } /* * Removes this iter from the list of iterators pointing to the parent list. */ template void kryListIterator::DisconnectFromList() { if(!this->m_list) { g_warning("Attempt to disconnect Iter from an empty list."); return; } this->m_list->RemoveIterator(this); this->m_invalid = TRUE; this->m_list = NULL; } /* * Returns the current node. * For kryList use only. */ template kryListNode *kryListIterator::GetNode() { return this->m_ptr; } /* * Invalidates the current iterator. */ template void kryListIterator::Invalidate() { this->m_invalid = TRUE; } /* * Called when an item is about to be added to the list we are iterating over. */ template void kryListIterator::NotifyBeforeAdd(kryListNode *node_before) { Validate(); if(this->m_ptr_next == node_before) this->Invalidate(); } /* * Called when an item is about to removed from the parent list. */ template void kryListIterator::NotifyBeforeRemove(kryListNode *node) { Validate(); if(!this->m_allow_remove_current || node != m_ptr) g_warning("bah (Remove)"); if((!this->m_allow_remove_current && this->m_ptr == node) || this->m_ptr_next == node) this->Invalidate(); } #include "krySignal.h" template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator; template class kryListIterator *>; template class kryListIterator *>;