From 9c275a93cec797a021571ba8545906e0b4ffbfbc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Sep 2011 10:20:47 +0200 Subject: Support for views; native part --- odb/object-result.hxx | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 odb/object-result.hxx (limited to 'odb/object-result.hxx') diff --git a/odb/object-result.hxx b/odb/object-result.hxx new file mode 100644 index 0000000..fcee125 --- /dev/null +++ b/odb/object-result.hxx @@ -0,0 +1,336 @@ +// file : odb/object-result.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_OBJECT_RESULT_HXX +#define ODB_OBJECT_RESULT_HXX + +#include + +#include // std::ptrdiff_t, std::size_t +#include // iterator categories + +#include +#include +#include + +#include + +namespace odb +{ + template + class result_impl: public details::shared_base + { + public: + virtual + ~result_impl (); + + protected: + friend class result; + friend class result_iterator; + + typedef odb::database database_type; + + typedef typename odb::object_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + + typedef typename odb::object_traits::object_type object_type; + typedef typename odb::object_traits::id_type id_type; + typedef odb::object_traits object_traits; + + result_impl (database_type& db) + : begin_ (true), end_ (false), db_ (db), current_ () + { + } + + database_type& + database () const + { + return db_; + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current (); + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + virtual void + load (object_type&) = 0; + + virtual id_type + load_id () = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: + void + current (pointer_type p) + { + current_ = p; + guard_.reset (current_); + } + + bool begin_; + bool end_; + + private: + database_type& db_; + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + template + class result_iterator + { + public: + typedef T value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + // T might be const T, but object_type is always T. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::id_type id_type; + + typedef result_impl result_impl_type; + + public: + explicit + result_iterator (result_impl_type* res = 0) + : res_ (res) + { + } + + // Input iterator requirements. + // + public: + reference + operator* () const + { + return pointer_traits::get_ref (res_->current ()); + } + + // Our value_type is already a pointer so return it instead of + // a pointer to it (operator-> will just have to go one deeper + // in the latter case). + // + pointer + operator-> () const + { + return pointer_traits::get_ptr (res_->current ()); + } + + result_iterator& + operator++ () + { + res_->next (); + return *this; + } + + result_iterator + operator++ (int) + { + // All non-end iterators for a result object move together. + // + res_->next (); + return *this; + } + + public: + typename object_traits::pointer_type + load () + { + typename object_traits::pointer_type r (res_->current ()); + res_->release (); + return r; + } + + void + load (object_type&); + + public: + bool + equal (result_iterator j) const + { + return (res_ ? res_->end () : true) == (j.res_ ? j.res_->end () : true); + } + + private: + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + result_impl_type* res_; + }; + + // Input iterator requirements. + // + template + inline bool + operator== (result_iterator i, + result_iterator j) + { + return i.equal (j); + } + + template + inline bool + operator!= (result_iterator i, + result_iterator j) + { + return !i.equal (j); + } + + // + // + template + class result + { + public: + typedef typename object_traits::pointer_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef result_iterator iterator; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef result_impl result_impl_type; + + public: + result () + { + } + + explicit + result (details::shared_ptr impl) + : impl_ (impl) + { + } + + // Copying or assignment of a result object leads to one instance + // being an alias for another. Think of copying a result as copying + // a file handle -- the file you access through either of them is + // still the same. + // + public: + result (const result& r) + : impl_ (r.impl_) + { + } + + result& + operator= (const result& r) + { + if (impl_ != r.impl_) + impl_ = r.impl_; + + return *this; + } + + void + swap (result& r) + { + // @@ add swap() to shared_ptr. + // + details::shared_ptr p (impl_); + impl_ = r.impl_; + r.impl_ = p; + } + + public: + iterator + begin () + { + if (impl_) + impl_->begin (); + + return iterator (impl_.get ()); + } + + iterator + end () + { + return iterator (); + } + + // Cache the result instead of fetching the data from the database + // one object at a time. This is necessary if you plan on performing + // database operations while iterating over the result. + // + public: + void + cache () + { + if (impl_) + impl_->cache (); + } + + public: + bool + empty () const + { + if (impl_ == 0) + return true; + + impl_->begin (); + return impl_->end (); + } + + // Size is only known in cached results. + // + size_type + size () const + { + return impl_ ? impl_->size () : 0; + } + + private: + details::shared_ptr impl_; + }; +} + +#include + +#include + +#endif // ODB_OBJECT_RESULT_HXX -- cgit v1.1