iterators.hpp

Go to the documentation of this file.
00001 #ifndef wali_nwa_query_details_ITERATORS_HPP
00002 #define wali_nwa_query_details_ITERATORS_HPP
00003 
00004 #include "opennwa/Nwa.hpp"
00005 
00006 #include <iterator>
00007 #include <utility>
00008 #include <algorithm>
00009 
00010 #include <boost/iterator/iterator_facade.hpp>
00011 #include <boost/iterator/iterator_adaptor.hpp>
00012 #include <boost/shared_ptr.hpp>
00013 
00014 namespace opennwa
00015 {
00016     namespace query
00017     {
00018       namespace details
00019       {
00020 
00021         namespace iterators
00022         {
00023 
00024           /// The following adapts any iterator with the same element type so
00025           /// that the iterator can be used
00026           template<typename ValueType, typename ReferenceType = ValueType &>
00027           class iterator_base
00028             : public boost::iterator_facade<iterator_base<ValueType, ReferenceType>,
00029                                             ValueType,
00030                                             boost::forward_traversal_tag,
00031                                             ReferenceType>
00032           {
00033             friend class boost::iterator_core_access;
00034             
00035           protected:
00036             virtual void increment() = 0;
00037             virtual ReferenceType dereference() const = 0;
00038 
00039           public:
00040             virtual bool equal(iterator_base const & other) const = 0;
00041             virtual iterator_base* clone() const = 0;
00042           };
00043           
00044 
00045           template<typename CPlusPlusIterator>
00046           class cplusplus_iterator_adapter
00047             : public iterator_base<typename std::iterator_traits<CPlusPlusIterator>::value_type,
00048                                    typename std::iterator_traits<CPlusPlusIterator>::reference>
00049           {
00050           private:
00051             CPlusPlusIterator backing;
00052             typedef typename std::iterator_traits<CPlusPlusIterator>::value_type ValueType;
00053             typedef typename std::iterator_traits<CPlusPlusIterator>::reference Reference;
00054 
00055           public:
00056             cplusplus_iterator_adapter()
00057             {}
00058 
00059             cplusplus_iterator_adapter(cplusplus_iterator_adapter const & other)
00060               : backing(other.backing)
00061             {}
00062 
00063             explicit cplusplus_iterator_adapter(CPlusPlusIterator iter)
00064               : backing(iter)
00065             {}
00066 
00067             
00068             virtual cplusplus_iterator_adapter* clone() const
00069             {
00070               return new cplusplus_iterator_adapter(*this);
00071             }
00072 
00073             virtual void increment()
00074             {
00075               ++backing;
00076             }
00077 
00078             virtual bool equal(iterator_base<ValueType, Reference> const & other) const
00079             {
00080               const cplusplus_iterator_adapter * p =
00081                 dynamic_cast<cplusplus_iterator_adapter const*>(&other);
00082               
00083               if (p) {
00084                 return backing == p->backing;
00085               }
00086               else {
00087                 return false;
00088               }
00089             }
00090 
00091             Reference dereference() const
00092             {
00093               return *backing;
00094             }
00095           };
00096           
00097 
00098 
00099           template<typename ValueType, typename ReferenceType = ValueType &>
00100           class iterator_base_wrapper
00101             : public boost::iterator_facade<iterator_base_wrapper<ValueType, ReferenceType>,
00102                                             ValueType,
00103                                             boost::forward_traversal_tag,
00104                                             ReferenceType>
00105           {
00106           private:
00107             // iterator_base_wrapper acts as the RAII class for this. I
00108             // really want a cloning smart pointer, but there isn't one
00109             // standard. So I'll do it myself.
00110             iterator_base<ValueType, ReferenceType> * backing;
00111 
00112           public:
00113             iterator_base_wrapper()
00114               : backing(0)
00115             {}
00116 
00117             iterator_base_wrapper(iterator_base_wrapper const & other)
00118               : backing(other.backing->clone())
00119             {}
00120 
00121             template<typename V, typename R>
00122             explicit iterator_base_wrapper(iterator_base<V, R> const & base)
00123               : backing(base.clone())
00124             {}
00125 
00126             /////////////////////////////
00127             // Functions to support RAII
00128 
00129           private:
00130             void swap(iterator_base_wrapper & other) const // throw()
00131             {
00132               std::swap(backing, other.backing);
00133             }
00134 
00135           public:
00136             iterator_base_wrapper & operator=(iterator_base_wrapper const & other)
00137             {
00138               // Copy-and-swap
00139               iterator_base_wrapper copy(other);
00140               swap(copy);
00141               return *this;
00142             }
00143 
00144             ~iterator_base_wrapper()
00145             {
00146               delete backing;
00147             }
00148 
00149             
00150           private:
00151             friend class boost::iterator_core_access;
00152             
00153             ////////////////////////////////
00154             // Iterator functions
00155             virtual void increment()
00156             {
00157               ++(*backing);
00158             }
00159 
00160             virtual bool equal(iterator_base_wrapper const & other) const
00161             {
00162               return backing->equal(*other.backing);
00163             }
00164 
00165             ReferenceType dereference() const
00166             {
00167               return **backing;
00168             }
00169           };
00170 
00171 
00172           template <typename BackingIterator>
00173           class iterator_sequence
00174             : public boost::iterator_facade<iterator_sequence<BackingIterator>,
00175                                             typename std::iterator_traits<BackingIterator>::value_type,
00176                                             boost::forward_traversal_tag,
00177                                             typename std::iterator_traits<BackingIterator>::reference>
00178           {
00179           public:
00180             typedef std::pair<BackingIterator, BackingIterator> IteratorRange;
00181             typedef typename std::iterator_traits<BackingIterator>::value_type ValueType;
00182             typedef typename std::iterator_traits<BackingIterator>::reference Reference;
00183 
00184           private:
00185             boost::shared_ptr<std::deque<IteratorRange> > ranges;
00186 
00187             void dump_empty_ranges()
00188             {
00189               while (!ranges->empty() && ranges->front().first == ranges->front().second) {
00190                 ranges->pop_front();
00191               }
00192             }
00193 
00194           protected:
00195             friend class boost::iterator_core_access;
00196 
00197             void increment()
00198             {
00199               // 'current' is ranges[0].first, so increment it
00200               ++(ranges->front().first);
00201               dump_empty_ranges();
00202             }
00203             
00204             Reference dereference() const
00205             {
00206               return *(ranges->front().first);
00207             }
00208 
00209             bool equal(iterator_sequence const & other) const
00210             {
00211               if (ranges->empty() && other.ranges->empty()) {
00212                 return true;
00213               }
00214               else if (ranges->empty() && other.ranges->empty()) {
00215                 return false;
00216               }
00217               else {
00218                 return ranges->front().first == other.ranges->front().first;
00219               }
00220             }
00221 
00222           public:
00223             iterator_sequence()
00224               : ranges(new std::deque<IteratorRange>())
00225             {}
00226             
00227             iterator_sequence(iterator_sequence const & other)
00228               : ranges(other.ranges)
00229             {}
00230 
00231             void append_range(BackingIterator left, BackingIterator right)
00232             {
00233               if (left != right) {
00234                 ranges->push_back(IteratorRange(left, right));
00235               }
00236             }
00237           };
00238 
00239           
00240 
00241       }
00242     }
00243   }
00244 }
00245 
00246 // Yo, Emacs!
00247 // Local Variables:
00248 //   c-file-style: "ellemtel"
00249 //   c-basic-offset: 2
00250 // End:
00251 
00252 #endif