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