X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fstlplus%2Fcontainers%2Fsafe_iterator.tpp;fp=src%2Fstlplus%2Fcontainers%2Fsafe_iterator.tpp;h=4bbf9b8b18029102df2387109f15389b190ff07d;hp=3296482fd6b46d28c214f2225ea167a6a8103fc9;hb=4f6e4488a55f7e3ba3f7485d78177f793c0eab9a;hpb=574af38ed616d1adfa5e6ce35f67cda1f707f89d diff --git a/src/stlplus/containers/safe_iterator.tpp b/src/stlplus/containers/safe_iterator.tpp index 3296482..4bbf9b8 100644 --- a/src/stlplus/containers/safe_iterator.tpp +++ b/src/stlplus/containers/safe_iterator.tpp @@ -1,373 +1,357 @@ -namespace stlplus -{ - - //////////////////////////////////////////////////////////////////////////////// - // body class implements the aliasing behaviour - - template - class safe_iterator_body - { - private: - const O* m_owner; - N* m_node; - unsigned m_count; - - public: - - safe_iterator_body(const O* owner, N* node) throw() : - m_owner(owner), m_node(node), m_count(1) - { -// std::cerr << "constructing " -// << std::hex << ((unsigned long)this) -// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) -// << ":" << std::dec << m_count << std::endl; - } - - ~safe_iterator_body(void) throw() - { -// std::cerr << "destroying " -// << std::hex << ((unsigned long)this) -// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) -// << ":" << std::dec << m_count << std::endl; - m_owner = 0; - m_node = 0; - } - - unsigned count(void) const - { - return m_count; - } - - void increment(void) - { - ++m_count; -// std::cerr << "incremented " -// << std::hex << ((unsigned long)this) -// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) -// << ":" << std::dec << m_count << std::endl; - } - - bool decrement(void) - { - --m_count; -// std::cerr << "decremented " -// << std::hex << ((unsigned long)this) -// << " => " << ((unsigned long)m_owner) << ":" << ((unsigned long)m_node) -// << ":" << std::dec << m_count << std::endl; - return m_count == 0; - } - - N* node(void) const throw() - { - return m_node; - } - - const O* owner(void) const throw() - { - return m_owner; - } - - void change_owner(const O* owner) - { - m_owner = owner; - } - - bool equal(const safe_iterator_body* right) const throw() - { -// return m_node == right->m_node; - return compare(right) == 0; - } - - int compare(const safe_iterator_body* right) const throw() - { - return ((long)m_node) - ((long)right->m_node); - } - - bool null(void) const throw() - { - return m_owner == 0; - } - - bool end(void) const throw() - { - return m_owner != 0 && m_node == 0; - } - - bool valid(void) const throw() - { - return m_owner != 0 && m_node != 0; - } - - void set_end(void) throw() - { - m_node = 0; - } - - void set_null(void) throw() - { - m_owner = 0; - m_node = 0; - } - - void assert_valid(void) const throw(null_dereference,end_dereference) - { - if (null()) - throw null_dereference("stlplus::safe_iterator"); - if (end()) - throw end_dereference("stlplus::safe_iterator"); - } - - void assert_non_null(void) const throw(null_dereference) - { - if (null()) - throw null_dereference("stlplus::safe_iterator"); - } - - void assert_owner(const O* owner) const throw(wrong_object) - { - if (owner != m_owner) - throw wrong_object("stlplus::safe_iterator"); - } - }; - - - //////////////////////////////////////////////////////////////////////////////// - // Master Iterator - //////////////////////////////////////////////////////////////////////////////// - - // construct a valid iterator - template - master_iterator::master_iterator(const O* owner, N* node) throw() : - m_body(new safe_iterator_body(owner,node)) - { - } - - // destructor - disconnect all iterators from the node - // this usually happens when the node is deleted and must invalidate all aliases - template - master_iterator::~master_iterator(void) throw() - { - m_body->set_end(); - if(m_body->decrement()) - { - delete m_body; - m_body = 0; - } - } - - // dereference - template - N* master_iterator::node(void) const throw() - { - return m_body->node(); - } - - template - const O* master_iterator::owner(void) const throw() - { - return m_body->owner(); - } - - // when you move a node from one owner to another, call this on the node's iterator - // this effectively moves all iterators to the node so that they are owned by the new owner too - template - void master_iterator::change_owner(const O* owner) throw() - { - m_body->change_owner(owner); - } - - //////////////////////////////////////////////////////////////////////////////// - // Safe Iterator - //////////////////////////////////////////////////////////////////////////////// - - // construct a null iterator - // later assignment of a valid iterator to this is done by using step - template - safe_iterator::safe_iterator(void) throw() : - m_body(new safe_iterator_body(0,0)) - { - } - - // construct a valid iterator by aliasing from the owner node's master iterator - template - safe_iterator::safe_iterator(const master_iterator& r) throw() : - m_body(0) - { - m_body = r.m_body; - m_body->increment(); - } - - // construct a valid iterator by aliasing from the owner node's master iterator - template - safe_iterator::safe_iterator(const safe_iterator& r) throw() : - m_body(0) - { - m_body = r.m_body; - m_body->increment(); - } - - // assignment implements dealiasing followed by aliasing - template - safe_iterator& safe_iterator::operator=(const safe_iterator& r) throw() - { - if (m_body != r.m_body) - { - if (m_body->decrement()) - delete m_body; - m_body = r.m_body; - m_body->increment(); - } - return *this; - } - - // destructor - implements dealiasing - template - safe_iterator::~safe_iterator(void) throw() - { - if(m_body->decrement()) - { - delete m_body; - m_body = 0; - } - } - - - // increment/decrement operation - // implements dealiasing followed by aliasing - template - void safe_iterator::set(const master_iterator& r) throw() - { - if (m_body != r.m_body) - { - if (m_body->decrement()) - delete m_body; - m_body = r.m_body; - m_body->increment(); - } - } - - // dereference - template - N* safe_iterator::node(void) const throw() - { - return m_body->node(); - } - - template - const O* safe_iterator::owner(void) const throw() - { - return m_body->owner(); - } - - // change to a null iterator - i.e. one that doees not belong to any object - // this does not affect any other iterators pointing to the same node - template - void safe_iterator::set_null(void) throw() - { - if (m_body->count() == 1) - { - // no aliases, so just make this null - m_body->set_null(); - } - else - { - // create a new body which is null so as not to affect any other aliases - m_body->decrement(); - m_body = new safe_iterator_body(0,0); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // operations for clients that do not have a master end iterator - // alternatively, have a master end iterator as part of the container - // and call constructor(master_end) or step(master_end) - - // construct an end iterator - template - safe_iterator::safe_iterator(const O* owner) throw() : - m_body(new safe_iterator_body(owner,0)) - { - } - - // change to an end iterator - e.g. as a result of incrementing off the end - template - void safe_iterator::set_end(void) throw() - { - if (m_body->count() == 1) - { - // no aliases, so just make this an end iterator - m_body->set_end(); - } - else - { - // create a new body which is null so as not to affect any other aliases - m_body->decrement(); - m_body = new safe_iterator_body(owner(),0); - } - } - - //////////////////////////////////////////////////////////////////////////////// - // tests - - // comparison - template - bool safe_iterator::equal(const safe_iterator& right) const throw() - { - return compare(right) == 0; - } - - template - int safe_iterator::compare(const safe_iterator& right) const throw() - { - if (m_body == right.m_body) return 0; - return m_body->compare(right.m_body); - } - - // a null iterator is one that has not been initialised with a value yet - template - bool safe_iterator::null(void) const throw() - { - return m_body->null(); - } - - // an end iterator is one that points to the end element of the list of nodes - template - bool safe_iterator::end(void) const throw() - { - return m_body->end(); - } - - // a valid iterator is one that can be dereferenced - template - bool safe_iterator::valid(void) const throw() - { - return m_body->valid(); - } - - // check the rules for a valid iterator that can be dereferenced - template - void safe_iterator::assert_valid(void) const throw(null_dereference,end_dereference) - { - m_body->assert_valid(); - } - - template - void safe_iterator::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference) - { - m_body->assert_valid(); - m_body->assert_owner(owner); - } - - template - void safe_iterator::assert_non_null(void) const throw(null_dereference) - { - m_body->assert_non_null(); - } - - template - void safe_iterator::assert_owner(const O* owner) const throw(wrong_object) - { - m_body->assert_owner(owner); - } - -} // end namespace stlplus +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // body class implements the aliasing behaviour + + template + class safe_iterator_body + { + private: + const O* m_owner; + N* m_node; + unsigned m_count; + + public: + + safe_iterator_body(const O* owner, N* node) throw() : + m_owner(owner), m_node(node), m_count(1) + { + } + + ~safe_iterator_body(void) throw() + { + m_owner = 0; + m_node = 0; + } + + unsigned count(void) const + { + return m_count; + } + + void increment(void) + { + ++m_count; + } + + bool decrement(void) + { + --m_count; + return m_count == 0; + } + + N* node(void) const throw() + { + return m_node; + } + + const O* owner(void) const throw() + { + return m_owner; + } + + void change_owner(const O* owner) + { + m_owner = owner; + } + + bool equal(const safe_iterator_body* right) const throw() + { + return m_node == right->m_node; + } + + int compare(const safe_iterator_body* right) const throw() + { + if (m_node == right->m_node) return 0; + return (m_node < right->m_node) ? -1 : 1; + } + + bool null(void) const throw() + { + return m_owner == 0; + } + + bool end(void) const throw() + { + return m_owner != 0 && m_node == 0; + } + + bool valid(void) const throw() + { + return m_owner != 0 && m_node != 0; + } + + void set_end(void) throw() + { + m_node = 0; + } + + void set_null(void) throw() + { + m_owner = 0; + m_node = 0; + } + + void assert_valid(void) const throw(null_dereference,end_dereference) + { + if (null()) + throw null_dereference("stlplus::safe_iterator: dereferencing null iterator"); + if (end()) + throw end_dereference("stlplus::safe_iterator: dereferencing end iterator"); + } + + void assert_non_null(void) const throw(null_dereference) + { + if (null()) + throw null_dereference("stlplus::safe_iterator: dereferencing null iterator"); + } + + void assert_owner(const O* owner) const throw(wrong_object) + { + if (owner != m_owner) + throw wrong_object("stlplus::safe_iterator: using iterator with wrong object"); + } + }; + + + //////////////////////////////////////////////////////////////////////////////// + // Master Iterator + //////////////////////////////////////////////////////////////////////////////// + + // construct a valid iterator + template + master_iterator::master_iterator(const O* owner, N* node) throw() : + m_body(new safe_iterator_body(owner,node)) + { + } + + // destructor - disconnect all iterators from the node + // this usually happens when the node is deleted and must invalidate all aliases + template + master_iterator::~master_iterator(void) throw() + { + m_body->set_end(); + if(m_body->decrement()) + { + delete m_body; + m_body = 0; + } + } + + // dereference + template + N* master_iterator::node(void) const throw() + { + return m_body->node(); + } + + template + const O* master_iterator::owner(void) const throw() + { + return m_body->owner(); + } + + // when you move a node from one owner to another, call this on the node's iterator + // this effectively moves all iterators to the node so that they are owned by the new owner too + template + void master_iterator::change_owner(const O* owner) throw() + { + m_body->change_owner(owner); + } + + //////////////////////////////////////////////////////////////////////////////// + // Safe Iterator + //////////////////////////////////////////////////////////////////////////////// + + // construct a null iterator + // later assignment of a valid iterator to this is done by using step + template + safe_iterator::safe_iterator(void) throw() : + m_body(new safe_iterator_body(0,0)) + { + } + + // construct a valid iterator by aliasing from the owner node's master iterator + template + safe_iterator::safe_iterator(const master_iterator& r) throw() : + m_body(0) + { + m_body = r.m_body; + m_body->increment(); + } + + // construct a valid iterator by aliasing from the owner node's master iterator + template + safe_iterator::safe_iterator(const safe_iterator& r) throw() : + m_body(0) + { + m_body = r.m_body; + m_body->increment(); + } + + // assignment implements dealiasing followed by aliasing + template + safe_iterator& safe_iterator::operator=(const safe_iterator& r) throw() + { + if (m_body != r.m_body) + { + if (m_body->decrement()) + delete m_body; + m_body = r.m_body; + m_body->increment(); + } + return *this; + } + + // destructor - implements dealiasing + template + safe_iterator::~safe_iterator(void) throw() + { + if(m_body->decrement()) + { + delete m_body; + m_body = 0; + } + } + + + // increment/decrement operation + // implements dealiasing followed by aliasing + template + void safe_iterator::set(const master_iterator& r) throw() + { + if (m_body != r.m_body) + { + if (m_body->decrement()) + delete m_body; + m_body = r.m_body; + m_body->increment(); + } + } + + // dereference + template + N* safe_iterator::node(void) const throw() + { + return m_body->node(); + } + + template + const O* safe_iterator::owner(void) const throw() + { + return m_body->owner(); + } + + // change to a null iterator - i.e. one that doees not belong to any object + // this does not affect any other iterators pointing to the same node + template + void safe_iterator::set_null(void) throw() + { + if (m_body->count() == 1) + { + // no aliases, so just make this null + m_body->set_null(); + } + else + { + // create a new body which is null so as not to affect any other aliases + m_body->decrement(); + m_body = new safe_iterator_body(0,0); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // operations for clients that do not have a master end iterator + // alternatively, have a master end iterator as part of the container + // and call constructor(master_end) or step(master_end) + + // construct an end iterator + template + safe_iterator::safe_iterator(const O* owner) throw() : + m_body(new safe_iterator_body(owner,0)) + { + } + + // change to an end iterator - e.g. as a result of incrementing off the end + template + void safe_iterator::set_end(void) throw() + { + if (m_body->count() == 1) + { + // no aliases, so just make this an end iterator + m_body->set_end(); + } + else + { + // create a new body which is null so as not to affect any other aliases + m_body->decrement(); + m_body = new safe_iterator_body(owner(),0); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // tests + + // comparison + template + bool safe_iterator::equal(const safe_iterator& right) const throw() + { + if (m_body == right.m_body) return true; + return m_body->equal(right.m_body); + } + + template + int safe_iterator::compare(const safe_iterator& right) const throw() + { + return m_body->compare(right.m_body); + } + + // a null iterator is one that has not been initialised with a value yet + template + bool safe_iterator::null(void) const throw() + { + return m_body->null(); + } + + // an end iterator is one that points to the end element of the list of nodes + template + bool safe_iterator::end(void) const throw() + { + return m_body->end(); + } + + // a valid iterator is one that can be dereferenced + template + bool safe_iterator::valid(void) const throw() + { + return m_body->valid(); + } + + // check the rules for a valid iterator that can be dereferenced + template + void safe_iterator::assert_valid(void) const throw(null_dereference,end_dereference) + { + m_body->assert_valid(); + } + + template + void safe_iterator::assert_valid(const O* owner) const throw(wrong_object,null_dereference,end_dereference) + { + m_body->assert_valid(); + m_body->assert_owner(owner); + } + + template + void safe_iterator::assert_non_null(void) const throw(null_dereference) + { + m_body->assert_non_null(); + } + + template + void safe_iterator::assert_owner(const O* owner) const throw(wrong_object) + { + m_body->assert_owner(owner); + } + +} // end namespace stlplus