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