4 ////////////////////////////////////////////////////////////////////////////////
5 // body class implements the aliasing behaviour
7 template<typename O, typename N>
8 class safe_iterator_body
17 safe_iterator_body(const O* owner, N* node) throw() :
18 m_owner(owner), m_node(node), m_count(1)
22 ~safe_iterator_body(void) throw()
28 unsigned count(void) const
44 N* node(void) const throw()
49 const O* owner(void) const throw()
54 void change_owner(const O* owner)
59 bool equal(const safe_iterator_body<O,N>* right) const throw()
61 return m_node == right->m_node;
64 int compare(const safe_iterator_body<O,N>* right) const throw()
66 if (m_node == right->m_node) return 0;
67 return (m_node < right->m_node) ? -1 : 1;
70 bool null(void) const throw()
75 bool end(void) const throw()
77 return m_owner != 0 && m_node == 0;
80 bool valid(void) const throw()
82 return m_owner != 0 && m_node != 0;
85 void set_end(void) throw()
90 void set_null(void) throw()
96 void assert_valid(void) const throw(null_dereference,end_dereference)
99 throw null_dereference("stlplus::safe_iterator: dereferencing null iterator");
101 throw end_dereference("stlplus::safe_iterator: dereferencing end iterator");
104 void assert_non_null(void) const throw(null_dereference)
107 throw null_dereference("stlplus::safe_iterator: dereferencing null iterator");
110 void assert_owner(const O* owner) const throw(wrong_object)
112 if (owner != m_owner)
113 throw wrong_object("stlplus::safe_iterator: using iterator with wrong object");
118 ////////////////////////////////////////////////////////////////////////////////
120 ////////////////////////////////////////////////////////////////////////////////
122 // construct a valid iterator
123 template<typename O, typename N>
124 master_iterator<O,N>::master_iterator(const O* owner, N* node) throw() :
125 m_body(new safe_iterator_body<O,N>(owner,node))
129 // destructor - disconnect all iterators from the node
130 // this usually happens when the node is deleted and must invalidate all aliases
131 template<typename O, typename N>
132 master_iterator<O,N>::~master_iterator(void) throw()
135 if(m_body->decrement())
143 template<typename O, typename N>
144 N* master_iterator<O,N>::node(void) const throw()
146 return m_body->node();
149 template<typename O, typename N>
150 const O* master_iterator<O,N>::owner(void) const throw()
152 return m_body->owner();
155 // when you move a node from one owner to another, call this on the node's iterator
156 // this effectively moves all iterators to the node so that they are owned by the new owner too
157 template<typename O, typename N>
158 void master_iterator<O,N>::change_owner(const O* owner) throw()
160 m_body->change_owner(owner);
163 ////////////////////////////////////////////////////////////////////////////////
165 ////////////////////////////////////////////////////////////////////////////////
167 // construct a null iterator
168 // later assignment of a valid iterator to this is done by using step
169 template<typename O, typename N>
170 safe_iterator<O,N>::safe_iterator(void) throw() :
171 m_body(new safe_iterator_body<O,N>(0,0))
175 // construct a valid iterator by aliasing from the owner node's master iterator
176 template<typename O, typename N>
177 safe_iterator<O,N>::safe_iterator(const master_iterator<O,N>& r) throw() :
184 // construct a valid iterator by aliasing from the owner node's master iterator
185 template<typename O, typename N>
186 safe_iterator<O,N>::safe_iterator(const safe_iterator<O,N>& r) throw() :
193 // assignment implements dealiasing followed by aliasing
194 template<typename O, typename N>
195 safe_iterator<O,N>& safe_iterator<O,N>::operator=(const safe_iterator<O,N>& r) throw()
197 if (m_body != r.m_body)
199 if (m_body->decrement())
207 // destructor - implements dealiasing
208 template<typename O, typename N>
209 safe_iterator<O,N>::~safe_iterator(void) throw()
211 if(m_body->decrement())
219 // increment/decrement operation
220 // implements dealiasing followed by aliasing
221 template<typename O, typename N>
222 void safe_iterator<O,N>::set(const master_iterator<O,N>& r) throw()
224 if (m_body != r.m_body)
226 if (m_body->decrement())
234 template<typename O, typename N>
235 N* safe_iterator<O,N>::node(void) const throw()
237 return m_body->node();
240 template<typename O, typename N>
241 const O* safe_iterator<O,N>::owner(void) const throw()
243 return m_body->owner();
246 // change to a null iterator - i.e. one that doees not belong to any object
247 // this does not affect any other iterators pointing to the same node
248 template<typename O, typename N>
249 void safe_iterator<O,N>::set_null(void) throw()
251 if (m_body->count() == 1)
253 // no aliases, so just make this null
258 // create a new body which is null so as not to affect any other aliases
260 m_body = new safe_iterator_body<O,N>(0,0);
264 ////////////////////////////////////////////////////////////////////////////////
265 // operations for clients that do not have a master end iterator
266 // alternatively, have a master end iterator as part of the container
267 // and call constructor(master_end) or step(master_end)
269 // construct an end iterator
270 template<typename O, typename N>
271 safe_iterator<O,N>::safe_iterator(const O* owner) throw() :
272 m_body(new safe_iterator_body<O,N>(owner,0))
276 // change to an end iterator - e.g. as a result of incrementing off the end
277 template<typename O, typename N>
278 void safe_iterator<O,N>::set_end(void) throw()
280 if (m_body->count() == 1)
282 // no aliases, so just make this an end iterator
287 // create a new body which is null so as not to affect any other aliases
289 m_body = new safe_iterator_body<O,N>(owner(),0);
293 ////////////////////////////////////////////////////////////////////////////////
297 template<typename O, typename N>
298 bool safe_iterator<O,N>::equal(const safe_iterator<O,N>& right) const throw()
300 if (m_body == right.m_body) return true;
301 return m_body->equal(right.m_body);
304 template<typename O, typename N>
305 int safe_iterator<O,N>::compare(const safe_iterator<O,N>& right) const throw()
307 return m_body->compare(right.m_body);
310 // a null iterator is one that has not been initialised with a value yet
311 template<typename O, typename N>
312 bool safe_iterator<O,N>::null(void) const throw()
314 return m_body->null();
317 // an end iterator is one that points to the end element of the list of nodes
318 template<typename O, typename N>
319 bool safe_iterator<O,N>::end(void) const throw()
321 return m_body->end();
324 // a valid iterator is one that can be dereferenced
325 template<typename O, typename N>
326 bool safe_iterator<O,N>::valid(void) const throw()
328 return m_body->valid();
331 // check the rules for a valid iterator that can be dereferenced
332 template<typename O, typename N>
333 void safe_iterator<O,N>::assert_valid(void) const throw(null_dereference,end_dereference)
335 m_body->assert_valid();
338 template<typename O, typename N>
339 void safe_iterator<O,N>::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference)
341 m_body->assert_valid();
342 m_body->assert_owner(owner);
345 template<typename O, typename N>
346 void safe_iterator<O,N>::assert_non_null(void) const throw(null_dereference)
348 m_body->assert_non_null();
351 template<typename O, typename N>
352 void safe_iterator<O,N>::assert_owner(const O* owner) const throw(wrong_object)
354 m_body->assert_owner(owner);
357 } // end namespace stlplus