list.cpp

Go to the documentation of this file.
00001 #ifndef LIST_IMPLEMENTATION_FILE
00002 #define LIST_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : list                                                              *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1998-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 // POLICIES:
00019 //
00020 // the cursor should never be stored to or deleted; it is merely a scanner that
00021 // runs through the list.
00022 //
00023 // the cursor can point at the head or tail.  any storage action is taken to
00024 // mean that it applies to the closest real object, if one exists.  any query
00025 // action is taken similarly.
00026 
00027 #include "list.h"
00028 #include "node.h"
00029 
00030 #include <basis/function.h>
00031 
00032 namespace nodes {
00033 
00034 // nice names for the positions of the next link and the previous link in
00035 // our node's indices.
00036 const int PREVIOUS = 0;
00037 const int NEXT = 1;
00038 
00040 
00041 // iterator functions:
00042 
00043 void list::iterator::operator ++()
00044 {
00045   if (is_tail()) return;  // already at the end.
00046   _cursor = _cursor->get_link(NEXT);
00047 }
00048 
00049 void list::iterator::operator --()
00050 {
00051   if (is_head()) return;  // already at the front.
00052   _cursor = _cursor->get_link(PREVIOUS);
00053 }
00054 
00055 bool list::iterator::operator ==(const iterator &to_compare) const
00056 { return _cursor == to_compare._cursor; }
00057 
00058 const node *list::iterator::observe()
00059 {
00060   if (!_manager || _manager->empty()) return NIL;
00061   if (*this == _manager->head()) next();
00062   if (*this == _manager->tail()) previous();
00063   return _cursor;
00064 }
00065 
00066 node *list::iterator::access()
00067 {
00068   if (!_manager || _manager->empty()) return NIL;
00069   if (*this == _manager->head()) next();
00070   if (*this == _manager->tail()) previous();
00071   return _cursor;
00072 }
00073 
00074 bool list::iterator::is_head() const
00075 {
00076   if (!_manager) return false;
00077   return _cursor == _manager->_head;
00078 }
00079 
00080 bool list::iterator::is_tail() const
00081 { 
00082   if (!_manager) return false;
00083   return _cursor == _manager->_tail;
00084 }
00085 
00086 void list::iterator::jump_head()
00087 {
00088   if (!_manager) return;
00089   _cursor = _manager->_head;
00090 }
00091 
00092 void list::iterator::jump_tail()
00093 {
00094   if (!_manager) return;
00095   _cursor = _manager->_tail;
00096 }
00097 
00099 
00100 list::list()
00101 : _head(NIL), _tail(NIL)
00102 {
00103   _head = new node(2);
00104   _tail = new node(2);
00105   _head->set_link(NEXT, _tail);
00106   _tail->set_link(PREVIOUS, _head);
00107 }
00108 
00109 list::~list()
00110 {
00111   iterator zapper = head();
00112   while (!empty())
00113     zap(zapper);
00114   WHACK(_head);
00115   WHACK(_tail);
00116 }
00117 
00118 bool list::empty() const
00119 {
00120   if (_head->get_link(NEXT) == _tail) return true;
00121   return false;
00122 }
00123 
00124 bool list::set_index(iterator &where, int new_index)
00125 {
00126   if (where._manager != this) return false;
00127   if (empty()) return false;
00128   node *skipper = _head->get_link(NEXT);
00129   for (int i = 0; i < new_index; i++) {
00130     skipper = skipper->get_link(NEXT);
00131     if (skipper == _tail) return false;  // out of bounds now.
00132   }
00133   where._cursor = skipper;
00134   return true;
00135 }
00136 
00137 bool list::forward(iterator &where, int count)
00138 { 
00139   if (where._manager != this) return false;
00140   if (count <= 0) return true;
00141   if (items_from_tail(where) < count) return false;
00142   if (where.is_head()) where.next();  // skip the head guard.
00143   for (int i = 0; i < count; i++) where.next();
00144   return true;
00145 }
00146 
00147 bool list::backward(iterator &where, int count)
00148 {
00149   if (where._manager != this) return false;
00150   if (count <= 0) return true;
00151   if (items_from_head(where) < count) return false;
00152   if (where.is_tail()) where.previous();  // skip the tail guard.
00153   for (int i = 0; i < count; i++) where.previous();
00154   return true;
00155 }
00156 
00157 int list::elements() const
00158 {
00159   if (empty()) return 0;
00160   int to_return = 0;
00161   node *skipper = _head->get_link(NEXT);
00162   while (skipper != _tail) {
00163     to_return++;
00164     skipper = skipper->get_link(NEXT);
00165   }
00166   return to_return;
00167 }
00168 
00169 int list::items_from_head(const iterator &where) const
00170 {
00171   if (where._manager != this) return 0;
00172   if (where.is_head()) return 0;  // make sure it's not there already.
00173   int index = 0;
00174   node *skipper = _head->get_link(NEXT);
00175   while ( (where._cursor != skipper) && (skipper != _tail) ) {
00176     index++;
00177     skipper = skipper->get_link(NEXT);
00178   }
00179   return index;
00180 }
00181 
00182 int list::items_from_tail(const iterator &where) const
00183 {
00184   if (where._manager != this) return 0;
00185   if (where.is_tail()) return 0;  // make sure it's not there already.
00186   int index = 0;
00187   node *skipper = _tail->get_link(PREVIOUS);
00188   while ( (where._cursor != skipper) && (skipper != _head) ) {
00189     index++;
00190     skipper = skipper->get_link(PREVIOUS);
00191   }
00192   return index;
00193 }
00194 
00195 /*
00196 node *list::get()
00197 {
00198   if (empty()) return NIL;  // make sure the list isn't empty.
00199   if (_cursor == _head) return _head->get_link(NEXT);
00200     // check special case for pointing at the head.
00201   if (_cursor == _tail) return _tail->get_link(PREVIOUS);
00202     // check special case for pointing at the tail.
00203   return _cursor;
00204 }
00205 */
00206 
00207 node *list::remove(iterator &where)
00208 {
00209   if (where._manager != this) return NIL;
00210   if (empty()) return NIL;
00211   if (where._cursor == _head)
00212     where._cursor = _head->get_link(NEXT);
00213   if (where._cursor == _tail)
00214     where._cursor = _tail->get_link(PREVIOUS);
00215   node *old_cursor = where._cursor;
00216   node *old_previous = old_cursor->get_link(PREVIOUS);
00217   node *old_next = old_cursor->get_link(NEXT);
00218   old_cursor->set_link(PREVIOUS, NIL);
00219   old_cursor->set_link(NEXT, NIL);
00220   old_previous->set_link(NEXT, old_next);
00221   old_next->set_link(PREVIOUS, old_previous);
00222   where._cursor = old_next;
00223   return old_cursor;
00224 }
00225 
00226 void list::zap(iterator &where) { delete remove(where); }
00227 
00228 void list::append(iterator &where, node *new_node)
00229 {
00230   if (where._manager != this) return;
00231   while (new_node->links() < 2) new_node->insert_link(0, NIL);
00232   if (empty()) where._cursor = _head;
00233   if (where._cursor == _tail)
00234     where._cursor = _tail->get_link(PREVIOUS);
00235     // shift from the tail sentinel to the tail element.
00236   node *save_next = where._cursor->get_link(NEXT);
00237   where._cursor->set_link(NEXT, new_node);
00238   new_node->set_link(PREVIOUS, where._cursor);
00239   new_node->set_link(NEXT, save_next);
00240   save_next->set_link(PREVIOUS, new_node);
00241   where._cursor = new_node;
00242 }
00243 
00244 void list::insert(iterator &where, node *new_node)
00245 {
00246   if (where._manager != this) return;
00247   while (new_node->links() < 2) new_node->insert_link(0, NIL);
00248   if (empty()) where._cursor = _tail;
00249   if (where._cursor == _head)
00250     where._cursor = _head->get_link(NEXT);
00251     // shift from head sentinel to the head element.
00252   node *save_prior = where._cursor->get_link(PREVIOUS);
00253   where._cursor->set_link(PREVIOUS, new_node);
00254   new_node->set_link(NEXT, where._cursor);
00255   new_node->set_link(PREVIOUS, save_prior);
00256   save_prior->set_link(NEXT, new_node);
00257   where._cursor = new_node;
00258 }
00259 
00260 void list::zap_all()
00261 {
00262   iterator zapper = head();
00263   while (!empty()) zap(zapper);
00264 }
00265 
00266 } // namespace.
00267 
00268 
00269 #endif //LIST_IMPLEMENTATION_FILE
00270 

Generated on Fri Nov 28 04:29:17 2008 for HOOPLE Libraries by  doxygen 1.5.1