+++ /dev/null
-
-
-
-/*****************************************************************************\
-* *
-* Name : list *
-* Author : Chris Koeritz *
-* *
-*******************************************************************************
-* Copyright (c) 1998-$now By Author. 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 of *
-* the License or (at your option) any later version. This is online at: *
-* http://www.fsf.org/copyleft/gpl.html *
-* Please send any updates to: fred@gruntose.com *
-\*****************************************************************************/
-
-// POLICIES:
-//
-// the cursor should never be stored to or deleted; it is merely a scanner that
-// runs through the list.
-//
-// the cursor can point at the head or tail. any storage action is taken to
-// mean that it applies to the closest real object, if one exists. any query
-// action is taken similarly.
-
-#include "list.h"
-#include "node.h"
-
-#include <basis/functions.h>
-
-namespace nodes {
-
-// nice names for the positions of the next link and the previous link in
-// our node's indices.
-const int PREVIOUS = 0;
-const int NEXT = 1;
-
-//////////////
-
-// iterator functions:
-
-void list::iterator::operator ++()
-{
- if (is_tail()) return; // already at the end.
- _cursor = _cursor->get_link(NEXT);
-}
-
-void list::iterator::operator --()
-{
- if (is_head()) return; // already at the front.
- _cursor = _cursor->get_link(PREVIOUS);
-}
-
-bool list::iterator::operator ==(const iterator &to_compare) const
-{ return _cursor == to_compare._cursor; }
-
-const node *list::iterator::observe()
-{
- if (!_manager || _manager->empty()) return NIL;
- if (*this == _manager->head()) next();
- if (*this == _manager->tail()) previous();
- return _cursor;
-}
-
-node *list::iterator::access()
-{
- if (!_manager || _manager->empty()) return NIL;
- if (*this == _manager->head()) next();
- if (*this == _manager->tail()) previous();
- return _cursor;
-}
-
-bool list::iterator::is_head() const
-{
- if (!_manager) return false;
- return _cursor == _manager->_head;
-}
-
-bool list::iterator::is_tail() const
-{
- if (!_manager) return false;
- return _cursor == _manager->_tail;
-}
-
-void list::iterator::jump_head()
-{
- if (!_manager) return;
- _cursor = _manager->_head;
-}
-
-void list::iterator::jump_tail()
-{
- if (!_manager) return;
- _cursor = _manager->_tail;
-}
-
-//////////////
-
-list::list()
-: _head(NIL), _tail(NIL)
-{
- _head = new node(2);
- _tail = new node(2);
- _head->set_link(NEXT, _tail);
- _tail->set_link(PREVIOUS, _head);
-}
-
-list::~list()
-{
- iterator zapper = head();
- while (!empty())
- zap(zapper);
- WHACK(_head);
- WHACK(_tail);
-}
-
-bool list::empty() const
-{
- if (_head->get_link(NEXT) == _tail) return true;
- return false;
-}
-
-bool list::set_index(iterator &where, int new_index)
-{
- if (where._manager != this) return false;
- if (empty()) return false;
- node *skipper = _head->get_link(NEXT);
- for (int i = 0; i < new_index; i++) {
- skipper = skipper->get_link(NEXT);
- if (skipper == _tail) return false; // out of bounds now.
- }
- where._cursor = skipper;
- return true;
-}
-
-bool list::forward(iterator &where, int count)
-{
- if (where._manager != this) return false;
- if (count <= 0) return true;
- if (items_from_tail(where) < count) return false;
- if (where.is_head()) where.next(); // skip the head guard.
- for (int i = 0; i < count; i++) where.next();
- return true;
-}
-
-bool list::backward(iterator &where, int count)
-{
- if (where._manager != this) return false;
- if (count <= 0) return true;
- if (items_from_head(where) < count) return false;
- if (where.is_tail()) where.previous(); // skip the tail guard.
- for (int i = 0; i < count; i++) where.previous();
- return true;
-}
-
-int list::elements() const
-{
- if (empty()) return 0;
- int to_return = 0;
- node *skipper = _head->get_link(NEXT);
- while (skipper != _tail) {
- to_return++;
- skipper = skipper->get_link(NEXT);
- }
- return to_return;
-}
-
-int list::items_from_head(const iterator &where) const
-{
- if (where._manager != this) return 0;
- if (where.is_head()) return 0; // make sure it's not there already.
- int index = 0;
- node *skipper = _head->get_link(NEXT);
- while ( (where._cursor != skipper) && (skipper != _tail) ) {
- index++;
- skipper = skipper->get_link(NEXT);
- }
- return index;
-}
-
-int list::items_from_tail(const iterator &where) const
-{
- if (where._manager != this) return 0;
- if (where.is_tail()) return 0; // make sure it's not there already.
- int index = 0;
- node *skipper = _tail->get_link(PREVIOUS);
- while ( (where._cursor != skipper) && (skipper != _head) ) {
- index++;
- skipper = skipper->get_link(PREVIOUS);
- }
- return index;
-}
-
-/*
-node *list::get()
-{
- if (empty()) return NIL; // make sure the list isn't empty.
- if (_cursor == _head) return _head->get_link(NEXT);
- // check special case for pointing at the head.
- if (_cursor == _tail) return _tail->get_link(PREVIOUS);
- // check special case for pointing at the tail.
- return _cursor;
-}
-*/
-
-node *list::remove(iterator &where)
-{
- if (where._manager != this) return NIL;
- if (empty()) return NIL;
- if (where._cursor == _head)
- where._cursor = _head->get_link(NEXT);
- if (where._cursor == _tail)
- where._cursor = _tail->get_link(PREVIOUS);
- node *old_cursor = where._cursor;
- node *old_previous = old_cursor->get_link(PREVIOUS);
- node *old_next = old_cursor->get_link(NEXT);
- old_cursor->set_link(PREVIOUS, NIL);
- old_cursor->set_link(NEXT, NIL);
- old_previous->set_link(NEXT, old_next);
- old_next->set_link(PREVIOUS, old_previous);
- where._cursor = old_next;
- return old_cursor;
-}
-
-void list::zap(iterator &where) { delete remove(where); }
-
-void list::append(iterator &where, node *new_node)
-{
- if (where._manager != this) return;
- while (new_node->links() < 2) new_node->insert_link(0, NIL);
- if (empty()) where._cursor = _head;
- if (where._cursor == _tail)
- where._cursor = _tail->get_link(PREVIOUS);
- // shift from the tail sentinel to the tail element.
- node *save_next = where._cursor->get_link(NEXT);
- where._cursor->set_link(NEXT, new_node);
- new_node->set_link(PREVIOUS, where._cursor);
- new_node->set_link(NEXT, save_next);
- save_next->set_link(PREVIOUS, new_node);
- where._cursor = new_node;
-}
-
-void list::insert(iterator &where, node *new_node)
-{
- if (where._manager != this) return;
- while (new_node->links() < 2) new_node->insert_link(0, NIL);
- if (empty()) where._cursor = _tail;
- if (where._cursor == _head)
- where._cursor = _head->get_link(NEXT);
- // shift from head sentinel to the head element.
- node *save_prior = where._cursor->get_link(PREVIOUS);
- where._cursor->set_link(PREVIOUS, new_node);
- new_node->set_link(NEXT, where._cursor);
- new_node->set_link(PREVIOUS, save_prior);
- save_prior->set_link(NEXT, new_node);
- where._cursor = new_node;
-}
-
-void list::zap_all()
-{
- iterator zapper = head();
- while (!empty()) zap(zapper);
-}
-
-} // namespace.
-
-
-
-