From 2b856f69d490f6cedffac03ecbed8fef318ecc43 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 5 Feb 2013 15:50:06 +0200 Subject: Add support for change-tracking containers ODB now supports "smart" ordered containers. Such containers get extra functions for updating and deleting individual elements. Based on this functionality implement two change-tracking containers: odb::vector (equivalent to std::vector) and QOdbList (equivalent to QList). New tests: common/container/change-tracking and qt/common/container/change- tracking. --- odb/vector-impl.ixx | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 odb/vector-impl.ixx (limited to 'odb/vector-impl.ixx') diff --git a/odb/vector-impl.ixx b/odb/vector-impl.ixx new file mode 100644 index 0000000..5a859c4 --- /dev/null +++ b/odb/vector-impl.ixx @@ -0,0 +1,169 @@ +// file : odb/vector-impl.ixx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifdef ODB_CXX11 +# include // std::swap +#else +# include // std::swap +#endif + +namespace odb +{ + // vector_impl + // + inline vector_impl:: + vector_impl () + : state_ (state_not_tracking), + size_ (0), tail_ (0), capacity_ (0), data_ (0) + { + } + +#ifdef ODB_CXX11 + inline vector_impl:: + vector_impl (vector_impl&& x) + : state_ (state_not_tracking), + size_ (0), tail_ (0), capacity_ (0), data_ (0) + { + swap (x); + } +#endif + + inline vector_impl:: + ~vector_impl () + { + if (data_ != 0) + operator delete (data_); + } + + inline void vector_impl:: + swap (vector_impl& x) + { + std::swap (state_, x.state_); + std::swap (size_, x.size_); + std::swap (tail_, x.tail_); + std::swap (capacity_, x.capacity_); + std::swap (data_, x.data_); + } + + inline void vector_impl:: + reserve (std::size_t n) + { + if (n > capacity_) + realloc (n); + } + + inline void vector_impl:: + stop () + { + state_ = state_not_tracking; + size_ = tail_ = 0; + } + + inline void vector_impl:: + change () + { + state_ = state_changed; + size_ = tail_ = 0; + } + + inline vector_impl::container_state_type vector_impl:: + state () const + { + return state_; + } + + inline bool vector_impl:: + tracking () const + { + return state_ == state_tracking; + } + + inline std::size_t vector_impl:: + size () const + { + return size_; + } + + inline std::size_t vector_impl:: + capacity () const + { + return capacity_; + } + + inline vector_impl::element_state_type vector_impl:: + state (std::size_t i) const + { + std::size_t r (i % 4); + unsigned char v (data_[i / 4]); + return static_cast ((v & mask_[r]) >> shift_[r]); + } + + inline void vector_impl:: + modify (std::size_t i, std::size_t n) + { + for (; n != 0; --n, ++i) + if (state (i) != state_inserted) + set (i, state_updated); + } + + inline void vector_impl:: + assign (std::size_t n) + { + if (tail_ != 0) + clear (); + + push_back (n); + } + + inline void vector_impl:: + resize (size_t n) + { + if (n < tail_) + pop_back (tail_ - n); + else if (n > tail_) + push_back (n - tail_); + } + + inline void vector_impl:: + set (std::size_t i, element_state_type s) + { + std::size_t r (i % 4); + i /= 4; + unsigned char v (static_cast (s)); + v <<= shift_[r]; + data_[i] = (data_[i] & ~mask_[r]) | v; + } + + // vector_base + // + inline void vector_base:: + _arm (transaction& t) const + { + tran_ = &t; + t.register_ (&rollback, + const_cast (this), + transaction::event_rollback, + 0, + &tran_); + } + + inline vector_base:: + vector_base (const vector_base& x) + : impl_ (x.impl_), tran_ (0) + { + // If the original is armed, then arm ourselves as well. + // + if (x.tran_ != 0) + _arm (*x.tran_); + } + + inline void vector_base:: + swap (vector_base& x) + { + impl_.swap (x.impl_); + + if (tran_ != 0 || x.tran_ != 0) + swap_tran (x); + } +} -- cgit v1.1