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)
20 // std::cerr << "constructing "
21 // << std::hex << ((unsigned long)this)
22 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
23 // << ":" << std::dec << m_count << std::endl;
26 ~safe_iterator_body(void) throw()
28 // std::cerr << "destroying "
29 // << std::hex << ((unsigned long)this)
30 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
31 // << ":" << std::dec << m_count << std::endl;
36 unsigned count(void) const
44 // std::cerr << "incremented "
45 // << std::hex << ((unsigned long)this)
46 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
47 // << ":" << std::dec << m_count << std::endl;
53 // std::cerr << "decremented "
54 // << std::hex << ((unsigned long)this)
55 // << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node)
56 // << ":" << std::dec << m_count << std::endl;
60 N* node(void) const throw()
65 const O* owner(void) const throw()
70 void change_owner(const O* owner)
75 bool equal(const safe_iterator_body<O,N>* right) const throw()
77 // return m_node == right->m_node;
78 return compare(right) == 0;
81 int compare(const safe_iterator_body<O,N>* right) const throw()
83 return ((long)m_node) - ((long)right->m_node);
86 bool null(void) const throw()
91 bool end(void) const throw()
93 return m_owner != 0 && m_node == 0;
96 bool valid(void) const throw()
98 return m_owner != 0 && m_node != 0;
101 void set_end(void) throw()
106 void set_null(void) throw()
112 void assert_valid(void) const throw(null_dereference,end_dereference)
115 throw null_dereference("stlplus::safe_iterator");
117 throw end_dereference("stlplus::safe_iterator");
120 void assert_non_null(void) const throw(null_dereference)
123 throw null_dereference("stlplus::safe_iterator");
126 void assert_owner(const O* owner) const throw(wrong_object)
128 if (owner != m_owner)
129 throw wrong_object("stlplus::safe_iterator");
134 ////////////////////////////////////////////////////////////////////////////////
136 ////////////////////////////////////////////////////////////////////////////////
138 // construct a valid iterator
139 template<typename O, typename N>
140 master_iterator<O,N>::master_iterator(const O* owner, N* node) throw() :
141 m_body(new safe_iterator_body<O,N>(owner,node))
145 // destructor - disconnect all iterators from the node
146 // this usually happens when the node is deleted and must invalidate all aliases
147 template<typename O, typename N>
148 master_iterator<O,N>::~master_iterator(void) throw()
151 if(m_body->decrement())
159 template<typename O, typename N>
160 N* master_iterator<O,N>::node(void) const throw()
162 return m_body->node();
165 template<typename O, typename N>
166 const O* master_iterator<O,N>::owner(void) const throw()
168 return m_body->owner();
171 // when you move a node from one owner to another, call this on the node's iterator
172 // this effectively moves all iterators to the node so that they are owned by the new owner too
173 template<typename O, typename N>
174 void master_iterator<O,N>::change_owner(const O* owner) throw()
176 m_body->change_owner(owner);
179 ////////////////////////////////////////////////////////////////////////////////
181 ////////////////////////////////////////////////////////////////////////////////
183 // construct a null iterator
184 // later assignment of a valid iterator to this is done by using step
185 template<typename O, typename N>
186 safe_iterator<O,N>::safe_iterator(void) throw() :
187 m_body(new safe_iterator_body<O,N>(0,0))
191 // construct a valid iterator by aliasing from the owner node's master iterator
192 template<typename O, typename N>
193 safe_iterator<O,N>::safe_iterator(const master_iterator<O,N>& r) throw() :
200 // construct a valid iterator by aliasing from the owner node's master iterator
201 template<typename O, typename N>
202 safe_iterator<O,N>::safe_iterator(const safe_iterator<O,N>& r) throw() :
209 // assignment implements dealiasing followed by aliasing
210 template<typename O, typename N>
211 safe_iterator<O,N>& safe_iterator<O,N>::operator=(const safe_iterator<O,N>& r) throw()
213 if (m_body != r.m_body)
215 if (m_body->decrement())
223 // destructor - implements dealiasing
224 template<typename O, typename N>
225 safe_iterator<O,N>::~safe_iterator(void) throw()
227 if(m_body->decrement())
235 // increment/decrement operation
236 // implements dealiasing followed by aliasing
237 template<typename O, typename N>
238 void safe_iterator<O,N>::set(const master_iterator<O,N>& r) throw()
240 if (m_body != r.m_body)
242 if (m_body->decrement())
250 template<typename O, typename N>
251 N* safe_iterator<O,N>::node(void) const throw()
253 return m_body->node();
256 template<typename O, typename N>
257 const O* safe_iterator<O,N>::owner(void) const throw()
259 return m_body->owner();
262 // change to a null iterator - i.e. one that doees not belong to any object
263 // this does not affect any other iterators pointing to the same node
264 template<typename O, typename N>
265 void safe_iterator<O,N>::set_null(void) throw()
267 if (m_body->count() == 1)
269 // no aliases, so just make this null
274 // create a new body which is null so as not to affect any other aliases
276 m_body = new safe_iterator_body<O,N>(0,0);
280 ////////////////////////////////////////////////////////////////////////////////
281 // operations for clients that do not have a master end iterator
282 // alternatively, have a master end iterator as part of the container
283 // and call constructor(master_end) or step(master_end)
285 // construct an end iterator
286 template<typename O, typename N>
287 safe_iterator<O,N>::safe_iterator(const O* owner) throw() :
288 m_body(new safe_iterator_body<O,N>(owner,0))
292 // change to an end iterator - e.g. as a result of incrementing off the end
293 template<typename O, typename N>
294 void safe_iterator<O,N>::set_end(void) throw()
296 if (m_body->count() == 1)
298 // no aliases, so just make this an end iterator
303 // create a new body which is null so as not to affect any other aliases
305 m_body = new safe_iterator_body<O,N>(owner(),0);
309 ////////////////////////////////////////////////////////////////////////////////
313 template<typename O, typename N>
314 bool safe_iterator<O,N>::equal(const safe_iterator<O,N>& right) const throw()
316 return compare(right) == 0;
319 template<typename O, typename N>
320 int safe_iterator<O,N>::compare(const safe_iterator<O,N>& right) const throw()
322 if (m_body == right.m_body) return 0;
323 return m_body->compare(right.m_body);
326 // a null iterator is one that has not been initialised with a value yet
327 template<typename O, typename N>
328 bool safe_iterator<O,N>::null(void) const throw()
330 return m_body->null();
333 // an end iterator is one that points to the end element of the list of nodes
334 template<typename O, typename N>
335 bool safe_iterator<O,N>::end(void) const throw()
337 return m_body->end();
340 // a valid iterator is one that can be dereferenced
341 template<typename O, typename N>
342 bool safe_iterator<O,N>::valid(void) const throw()
344 return m_body->valid();
347 // check the rules for a valid iterator that can be dereferenced
348 template<typename O, typename N>
349 void safe_iterator<O,N>::assert_valid(void) const throw(null_dereference,end_dereference)
351 m_body->assert_valid();
354 template<typename O, typename N>
355 void safe_iterator<O,N>::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference)
357 m_body->assert_valid();
358 m_body->assert_owner(owner);
361 template<typename O, typename N>
362 void safe_iterator<O,N>::assert_non_null(void) const throw(null_dereference)
364 m_body->assert_non_null();
367 template<typename O, typename N>
368 void safe_iterator<O,N>::assert_owner(const O* owner) const throw(wrong_object)
370 m_body->assert_owner(owner);
373 } // end namespace stlplus