Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/gen/link.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: link.h,v 1.2 2002/08/24 13:55:15 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_GEN_LINK_H
00031 #define MORE_GEN_LINK_H
00032 
00033 #include <iterator>
00034 #include <cstdlib>
00035 
00036 
00037 namespace more {
00038 namespace gen {
00039 
00040   using std::size_t;
00041 
00042   template<typename T> class link;
00043 
00044   /** \class linked link.h more/gen/link.h
00045    **
00046    ** A class for linking objects together. This allows you for
00047    ** instance to link objects on the stack into a (unordered)
00048    ** list. */
00049   struct linked
00050   {
00051       /** construct a link which is a member of gr. gr may be eigher a
00052        * linked object or a link<T>. */
00053       explicit linked(linked& gr)
00054       {
00055           m_next = &gr;
00056           m_prev = gr.m_prev;
00057           gr.m_prev = this;
00058           m_prev->m_next = this;
00059       }
00060 
00061       /** construct a node to be later linked in with the link member
00062        * function. */
00063       linked() { m_prev = m_next = this; }
00064 
00065       /** unlink and destruct. */
00066       ~linked() { unlink(); }
00067 
00068       /** link in a node which as constructed by the default constructor. */
00069       void link_to(linked& gr)
00070       {
00071           unlink();
00072           m_next = &gr;
00073           m_prev = gr.m_prev;
00074           gr.m_prev = this;
00075           m_prev->m_next = this;
00076       }
00077 
00078       /** join with another link. */
00079       void join(linked& x)
00080       {
00081           linked* tmp = m_next;
00082           m_next = x.m_next;
00083           m_next->m_prev = this;
00084           x.m_next = tmp;
00085           tmp->m_prev = &x;
00086       }
00087 
00088       /** Join ln so that the next node becomes ln. */
00089       void join_after(linked* ln)
00090       {
00091           ln->m_prev->m_next = m_next;
00092           m_next->m_prev = ln->m_prev;
00093           m_next = ln;
00094           ln->m_prev = this;
00095       }
00096 
00097       /** Join ln so that the previous node becomes ln. */
00098       void join_before(linked* ln)
00099       {
00100           ln->m_next->m_prev = m_prev;
00101           m_prev->m_next = ln->m_next;
00102           m_prev = ln;
00103           ln->m_next = this;
00104       }
00105 
00106       /** unlink. */
00107       void unlink()
00108       {
00109           m_next->m_prev = m_prev;
00110           m_prev->m_next = m_next;
00111           m_prev = m_next = this;
00112       }
00113 
00114       bool is_linked() { return m_prev != this; }
00115 
00116       /** swap the possitions of the linked objects, possibly between
00117        * different rings. */
00118       friend void swap(linked& x, linked& y) {
00119           linked* tmp;
00120           tmp = x.m_prev; x.m_prev = y.m_prev; y.m_prev = tmp;
00121           tmp = x.m_next; x.m_next = y.m_next; y.m_next = tmp;
00122 //        std::swap(x.m_prev, y.m_prev);
00123 //        std::swap(x.m_next, y.m_next);
00124       }
00125 
00126     private:
00127       linked* m_prev;
00128       linked* m_next;
00129 
00130       template<typename T> friend class link;
00131   };
00132 
00133   /** \class link link.h more/gen/link.h
00134    **
00135    ** A container of linked objects. */
00136   template<typename T = linked>
00137     struct link : public linked
00138     {
00139         typedef size_t size_type;
00140         typedef T value_type;
00141         typedef T& reference;
00142         typedef T const& const_reference;
00143         typedef T* pointer;
00144         typedef T const* const_pointer;
00145 
00146         /** Constructs an empty container. */
00147         link() {}
00148 
00149         class const_iterator;
00150 
00151         /** A bidirectional iterator over \c T. */
00152         struct iterator
00153             : std::iterator<std::bidirectional_iterator_tag, T>
00154         {
00155             iterator() {}
00156             iterator(iterator const& it) : ln(it.ln) {}
00157             iterator(linked* ln_) : ln(ln_) {}
00158             iterator& operator=(iterator const& it)
00159             {
00160                 ln = it.ln; return *this;
00161             }
00162 
00163             bool operator==(iterator const& rhs) const { return ln == rhs.ln; }
00164             bool operator!=(iterator const& rhs) const { return ln != rhs.ln; }
00165 
00166             iterator& operator++() { ln = next(ln); return *this; }
00167             iterator& operator--() { ln = prev(ln); return *this; }
00168             iterator operator++(int)
00169             {
00170                 iterator tmp = *this;
00171                 ++*this;
00172                 return tmp;
00173             }
00174             iterator operator--(int)
00175             {
00176                 iterator tmp = *this;
00177                 --*this;
00178                 return tmp;
00179             }
00180 
00181             T& operator*() { return *static_cast<T*>(ln); }
00182             T* operator->() { return static_cast<T*>(ln); }
00183 
00184           private:
00185             linked* ln;
00186             friend class const_iterator;
00187         };
00188 
00189         /** A constant valued bidirectional iterator over \c T. */
00190         struct const_iterator
00191             : std::iterator<std::bidirectional_iterator_tag, const T>
00192         {
00193             const_iterator() {}
00194             const_iterator(const_iterator const& it) : ln(it.ln) {}
00195             const_iterator(iterator const& it) : ln(it.ln) {}
00196             const_iterator(const linked* ln_) : ln(ln_) {}
00197             const_iterator& operator=(const_iterator const& it)
00198             {
00199                 ln = it.ln; return *this;
00200             }
00201 
00202             bool operator==(const_iterator const& rhs) const
00203             {
00204                 return ln == rhs.ln;
00205             }
00206             bool operator!=(const_iterator const& rhs) const
00207             {
00208                 return ln != rhs.ln;
00209             }
00210 
00211             const_iterator& operator++() { ln = next(ln); return *this; }
00212             const_iterator& operator--() { ln = prev(ln); return *this; }
00213             const_iterator operator++(int)
00214             {
00215                 const_iterator tmp = *this;
00216                 ++*this;
00217                 return tmp;
00218             }
00219             const_iterator operator--(int)
00220             {
00221                 const_iterator tmp = *this;
00222                 --*this;
00223                 return tmp;
00224             }
00225 
00226             T const& operator*() { return *static_cast<T const*>(ln); }
00227             T const* operator->() { return static_cast<T const*>(ln); }
00228 
00229           private:
00230             const linked* ln;
00231         };
00232 
00233         typedef std::reverse_iterator<iterator> reverse_iterator;
00234         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00235 
00236         /** Start of the range of linked objects. */
00237         iterator        begin() { return iterator(m_next); }
00238         /** Past the end of the range of linked objects. */
00239         iterator        end() { return iterator(this); }
00240 
00241         reverse_iterator rbegin() { return reverse_iterator(end()); }
00242         reverse_iterator rend() { return reverse_iterator(begin()); }
00243 
00244         const_iterator  begin() const { return const_iterator(m_next); }
00245         const_iterator  end() const { return const_iterator(this); }
00246 
00247         const_reverse_iterator rbegin() const
00248         {
00249             return const_reverse_iterator(end());
00250         }
00251         const_reverse_iterator rend() const
00252         {
00253             return const_reverse_iterator(begin());
00254         }
00255 
00256         bool            empty() const { return m_next == this; }
00257 
00258         /** Join ln so that it becomes the first node. */
00259         void            join_front(linked* ln) { join_after(ln); }
00260         /** Join ln so that it becomes the last node. */
00261         void            join_back(linked* ln) { join_before(ln); }
00262 
00263         reference       front() { return static_cast<reference>(*m_next); }
00264         reference       back()  { return static_cast<reference>(*m_prev); }
00265 
00266         const_reference front() const
00267         {
00268             return static_cast<const_reference>(*m_next);
00269         }
00270         const_reference back()  const
00271         {
00272             return static_cast<const_reference>(*m_prev);
00273         }
00274 
00275       private:
00276         // Friendship with linked is not inherited to iterator.
00277         static linked* next(linked* ln) { return ln->m_next; }
00278         static linked* prev(linked* ln) { return ln->m_prev; }
00279         static linked const* next(linked const* ln) { return ln->m_next; }
00280         static linked const* prev(linked const* ln) { return ln->m_prev; }
00281 
00282         friend class iterator;
00283         friend class const_iterator;
00284         friend class linked;
00285     };
00286 
00287 }} // more::gen
00288 
00289 #endif

Generated on Sat Sep 7 19:11:12 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.