/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HDR_tlStableVector #define HDR_tlStableVector #include #include #include namespace tl { /** * @brief A stable vector class * * Unlike the normal vector, the stable vector guarantees that the * objects stored within are not relocated to other memory locations * even if the vector reallocates memory. * The stable vector does this by maintaining pointers rather than * objects itself. * This way, this container is able to store objects that do not have * a copy semantics. * * The stable vector offers two iterators: a usual one and a stable one. * While the usual iterator is invalidated if the vector reallocates * (the iterator gets invalid, not the location of the objects them- * selves), the stable iterator stays valid even if the container * reallocates. The stable iterator is a pointer to the container plus * an index. */ template class stable_vector { public: typedef X value_type; class iterator; class const_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef X value_type; typedef const X &reference; typedef const X *pointer; const_iterator () : m_iter () { // .. nothing yet .. } const_iterator (const const_iterator &d) : m_iter (d.m_iter) { // .. nothing yet .. } const_iterator (const iterator &d) : m_iter (d.m_iter) { // .. nothing yet .. } const_iterator (typename std::vector::const_iterator d) : m_iter (d) { // .. nothing yet .. } const_iterator &operator= (const_iterator d) { m_iter = d.m_iter; return *this; } const iterator &operator= (iterator d) { m_iter = d.m_iter; return *this; } bool operator== (const_iterator d) const { return m_iter == d.m_iter; } bool operator!= (const_iterator d) const { return m_iter != d.m_iter; } bool operator< (const_iterator d) const { return m_iter < d.m_iter; } ptrdiff_t operator- (const_iterator d) const { return m_iter - d.m_iter; } const_iterator operator- (ptrdiff_t n) const { return m_iter - n; } const_iterator operator+ (ptrdiff_t n) const { return m_iter + n; } const_iterator &operator+= (ptrdiff_t n) { m_iter += n; return *this; } const_iterator &operator-= (ptrdiff_t n) { m_iter -= n; return *this; } const_iterator &operator++ () { ++m_iter; return *this; } const_iterator operator++ (int) { const_iterator i = *this; ++m_iter; return i; } const_iterator &operator-- () { --m_iter; return *this; } const_iterator operator-- (int) { const_iterator i = *this; --m_iter; return i; } const X &operator[] (ptrdiff_t n) const { return *m_iter [n]; } const X &operator* () const { return **m_iter; } const X *operator-> () const { return *m_iter; } private: typename std::vector::const_iterator m_iter; }; class iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef X value_type; typedef X &reference; typedef X *pointer; iterator () : m_iter () { // .. nothing yet .. } iterator (const iterator &d) : m_iter (d.m_iter) { // .. nothing yet .. } iterator (typename std::vector::iterator d) : m_iter (d) { // .. nothing yet .. } iterator &operator= (iterator d) { m_iter = d.m_iter; return *this; } bool operator== (iterator d) const { return m_iter == d.m_iter; } bool operator!= (iterator d) const { return m_iter != d.m_iter; } bool operator< (iterator d) const { return m_iter < d.m_iter; } ptrdiff_t operator- (iterator d) const { return m_iter - d.m_iter; } iterator operator- (ptrdiff_t n) const { return m_iter - n; } iterator operator+ (ptrdiff_t n) const { return m_iter + n; } iterator &operator+= (ptrdiff_t n) { m_iter += n; return *this; } iterator &operator-= (ptrdiff_t n) { m_iter -= n; return *this; } iterator &operator++ () { ++m_iter; return *this; } iterator operator++ (int) { iterator i = *this; ++m_iter; return i; } iterator &operator-- () { --m_iter; return *this; } iterator operator-- (int) { iterator i = *this; --m_iter; return i; } X &operator[] (ptrdiff_t n) const { return *m_iter [n]; } X &operator* () const { return **m_iter; } X *operator-> () const { return *m_iter; } private: typename std::vector::iterator m_iter; friend class stable_vector::const_iterator; }; class stable_iterator; class stable_const_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef X value_type; typedef const X &reference; typedef const X *pointer; stable_const_iterator () : mp_vector (0), m_index (0) { // .. nothing yet .. } stable_const_iterator (const stable_const_iterator &d) : mp_vector (d.mp_vector), m_index (d.m_index) { // .. nothing yet .. } stable_const_iterator (const stable_iterator &d) : mp_vector (d.mp_vector), m_index (d.m_index) { // .. nothing yet .. } stable_const_iterator (const std::vector &v, size_t index) : mp_vector (&v), m_index (index) { // .. nothing yet .. } stable_const_iterator &operator= (stable_const_iterator d) { mp_vector = d.mp_vector; m_index = d.m_index; return *this; } stable_const_iterator &operator= (stable_iterator d) { mp_vector = d.mp_vector; m_index = d.m_index; return *this; } bool operator== (stable_const_iterator d) const { return mp_vector == d.mp_vector && m_index == d.m_index; } bool operator!= (stable_const_iterator d) const { return !operator== (d); } bool operator< (stable_const_iterator d) const { return m_index < d.m_index; } ptrdiff_t operator- (stable_const_iterator d) const { return m_index - d.m_index; } stable_const_iterator operator+ (ptrdiff_t n) const { return stable_const_iterator (*mp_vector, m_index + n); } stable_const_iterator operator- (ptrdiff_t n) const { return stable_const_iterator (*mp_vector, m_index - n); } stable_const_iterator &operator+= (ptrdiff_t n) { m_index += n; return *this; } stable_const_iterator &operator-= (ptrdiff_t n) { m_index -= n; return *this; } stable_const_iterator &operator++ () { ++m_index; return *this; } stable_const_iterator operator++ (int) { stable_const_iterator i = *this; ++m_index; return i; } stable_const_iterator &operator-- () { --m_index; return *this; } stable_const_iterator operator-- (int) { stable_const_iterator i = *this; --m_index; return i; } const X &operator[] (ptrdiff_t n) const { return *(*mp_vector) [m_index + n]; } const X &operator* () const { return *(*mp_vector) [m_index]; } const X *operator-> () const { return (*mp_vector) [m_index]; } size_t index () const { return m_index; } private: const std::vector *mp_vector; size_t m_index; }; class stable_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef X value_type; typedef X &reference; typedef X *pointer; stable_iterator () : mp_vector (0), m_index (0) { // .. nothing yet .. } stable_iterator (const stable_iterator &d) : mp_vector (d.mp_vector), m_index (d.m_index) { // .. nothing yet .. } stable_iterator (std::vector &v, size_t index) : mp_vector (&v), m_index (index) { // .. nothing yet .. } stable_iterator &operator= (stable_iterator d) { mp_vector = d.mp_vector; m_index = d.m_index; return *this; } bool operator== (stable_iterator d) const { return mp_vector == d.mp_vector && m_index == d.m_index; } bool operator!= (stable_iterator d) const { return !operator== (d); } bool operator< (stable_iterator d) const { return m_index < d.m_index; } ptrdiff_t operator- (stable_iterator d) const { return m_index - d.m_index; } stable_iterator operator+ (ptrdiff_t n) const { return stable_iterator (*mp_vector, m_index + n); } stable_iterator operator- (ptrdiff_t n) const { return stable_iterator (*mp_vector, m_index - n); } stable_iterator &operator+= (ptrdiff_t n) { m_index += n; return *this; } stable_iterator &operator-= (ptrdiff_t n) { m_index -= n; return *this; } stable_iterator &operator++ () { ++m_index; return *this; } stable_iterator operator++ (int) { stable_iterator i = *this; ++m_index; return i; } stable_iterator &operator-- () { --m_index; return *this; } stable_iterator operator-- (int) { stable_iterator i = *this; --m_index; return i; } X &operator[] (ptrdiff_t n) const { return *(*mp_vector) [m_index + n]; } X &operator* () const { return *(*mp_vector) [m_index]; } X *operator-> () const { return (*mp_vector) [m_index]; } size_t index () const { return m_index; } private: std::vector *mp_vector; size_t m_index; friend class stable_vector::stable_const_iterator; }; stable_vector () : m_objects () { // .. nothing yet .. } stable_vector (const stable_vector &d) : m_objects () { operator= (d); } ~stable_vector () { delete_objects (); } void reserve (size_t n) { m_objects.reserve (n); } stable_vector &operator= (const stable_vector &d) { if (&d != this) { delete_objects (); m_objects.reserve (d.size ()); for (typename std::vector ::const_iterator c = d.m_objects.begin (); c != d.m_objects.end (); ++c) { m_objects.push_back (new X (**c)); } } return *this; } bool operator== (const stable_vector &d) const { if (size () != d.size ()) { return false; } for (typename std::vector ::const_iterator a = m_objects.begin (), b = d.m_objects.begin (); a != m_objects.end (); ++a, ++b) { if (**a != **b) { return false; } } return true; } bool operator!= (const stable_vector &d) const { return !operator== (d); } bool operator< (const stable_vector &d) const { if (size () != d.size ()) { return size () < d.size (); } for (typename std::vector ::const_iterator a = m_objects.begin (), b = d.m_objects.begin (); a != m_objects.end (); ++a, ++b) { if (**a != **b) { return **a < **b; } } return false; } void clear () { delete_objects (); } bool empty () const { return m_objects.empty (); } void swap (stable_vector &d) { m_objects.swap (d.m_objects); } void push_back (const X &o) { m_objects.push_back (new X (o)); } void push_back (X *o) { m_objects.push_back (o); } const X &back () const { return *m_objects.back (); } const X &front () const { return *m_objects.front (); } X &back () { return *m_objects.back (); } X &front () { return *m_objects.front (); } void pop_back () { delete m_objects.back (); m_objects.pop_back (); } stable_iterator insert (stable_iterator pos, const X &value) { m_objects.insert (m_objects.begin () + pos.index (), new X (value)); return pos; } stable_iterator insert (stable_iterator pos, X *value) { m_objects.insert (m_objects.begin () + pos.index (), value); return pos; } void erase (stable_iterator pos) { typename std::vector ::iterator p = m_objects.begin () + pos.index (); delete *p; m_objects.erase (p); } void erase (stable_iterator from, stable_iterator to) { typename std::vector ::iterator p = m_objects.begin () + from.index (); typename std::vector ::iterator q = m_objects.begin () + to.index (); for (typename std::vector ::iterator i = p; i != q; ++i) { delete *i; } m_objects.erase (p, q); } iterator insert (iterator pos, const X &value) { size_t p = pos - begin (); m_objects.insert (m_objects.begin () + p, new X (value)); return begin () + p; } iterator insert (iterator pos, X *value) { size_t p = pos - begin (); m_objects.insert (m_objects.begin () + p, value); return begin () + p; } void erase (iterator pos) { typename std::vector ::iterator p = m_objects.begin () + (pos - begin ()); delete *p; m_objects.erase (p); } void erase (iterator from, iterator to) { typename std::vector ::iterator p = m_objects.begin () + (from - begin ()); typename std::vector ::iterator q = m_objects.begin () + (to - begin ()); for (typename std::vector ::iterator i = p; i != q; ++i) { delete *i; } m_objects.erase (p, q); } X &operator[] (size_t i) { return *m_objects [i]; } const X &operator[] (size_t i) const { return *m_objects [i]; } stable_iterator begin_stable () { return stable_iterator (m_objects, 0); } stable_const_iterator begin_stable () const { return stable_const_iterator (m_objects, 0); } stable_iterator end_stable () { return stable_iterator (m_objects, size ()); } stable_const_iterator end_stable () const { return stable_const_iterator (m_objects, size ()); } iterator begin () { return iterator (m_objects.begin ()); } const_iterator begin () const { return const_iterator (m_objects.begin ()); } iterator end () { return iterator (m_objects.end ()); } const_iterator end () const { return const_iterator (m_objects.end ()); } size_t size () const { return m_objects.size (); } private: std::vector m_objects; void delete_objects () { for (typename std::vector ::iterator c = m_objects.begin (); c != m_objects.end (); ++c) { delete *c; } m_objects.clear (); } }; } // namespace tl #endif