Mirror reflection library - Lagoon run-time layer 0.5.13

lagoon/range/std_range.hpp

Go to the documentation of this file.
00001 
00010 #ifndef LAGOON_RANGE_STD_RANGE_1011291729_HPP
00011 #define LAGOON_RANGE_STD_RANGE_1011291729_HPP
00012 
00013 #include <lagoon/utils.hpp>
00014 #include <lagoon/range/fwd_decl.hpp>
00015 #include <cassert>
00016 
00017 LAGOON_NAMESPACE_BEGIN
00018 
00019 namespace aux {
00020 
00021 // Forward declaration of the std range adaptor
00022 template <class Range>
00023 class std_range_adapt;
00024 
00025 // Forward declaration of the std range input iterator adaptor
00026 template <class Range>
00027 class std_input_iter_adapt;
00028 
00029 // A helper class used in iterator postincrement and dereference
00030 template <class Range, typename Value>
00031 class std_range_iter_deref
00032 {
00033 private:
00034     // The value pointed to by the iterator before post-increment
00035     Value value;
00036 
00037     inline std_range_iter_deref(const Value& val)
00038      : value(val)
00039     { }
00040 
00041     friend class std_input_iter_adapt<Range>;
00042 public:
00043     // The only thing this class allows to do is to dereference
00044     inline const Value& operator * (void) const
00045     {
00046         return value;
00047     }
00048 };
00049 
00050 // Generic std input iterator for interating over any Lagoon Range
00051 // Specific cases are handled by specializations of this
00052 // and the std_range_adapt template
00053 template <class Range>
00054 class std_input_iter_adapt
00055 {
00056 private:
00057     // Helper class holding references to the parent range
00058     // and to a local copy used for iteration
00059     class range_holder
00060     {
00061     private:
00062         // Local copy of the range used for iteration
00063         Range* range;
00064         // Points to the parent range that instantiated this iterator
00065         const Range* parent_ref;
00066     public:
00067         inline range_holder(void)
00068          : range(nullptr)
00069          , parent_ref(nullptr)
00070         { }
00071 
00072         inline range_holder(const range_holder& other)
00073          : range(other.range ? new Range(*other.range): nullptr)
00074          , parent_ref(other.parent_ref)
00075         { }
00076 
00077         inline range_holder(const Range& rng)
00078          : range(new Range(rng))
00079          , parent_ref(&rng)
00080         { }
00081 
00082         inline range_holder(const Range& rng, int)
00083          : range(nullptr)
00084          , parent_ref(&rng)
00085         { }
00086 
00087         inline ~range_holder(void)
00088         {
00089             if(range != nullptr) delete range;
00090         }
00091 
00092         inline range_holder& operator = (const range_holder& other)
00093         {
00094             if(range != nullptr) delete range;
00095             range = other.range? new Range(*other.range):nullptr;
00096             parent_ref = other.parent_ref;
00097         }
00098 
00099         inline bool at_end(void) const
00100         {
00101             return (parent_ref == nullptr) ||
00102                 (range == nullptr) ||
00103                 ((range != nullptr) && range->empty());
00104         }
00105 
00106         // checks the range positions for equality
00107         friend bool equal(
00108             const range_holder& a,
00109             const range_holder& b
00110         )
00111         {
00112             // if the ranges don't have the same parent
00113             // then they can't be equal
00114             if(a.parent_ref != b.parent_ref) return false;
00115             // if both iterators are 'non-end'
00116             if(a.range && b.range)
00117                 // compare their position
00118                 return same_position(*a.range, *b.range);
00119             // otherwise one of the ranges is an end range
00120             // and the other must be empty
00121             else return
00122                 (a.range && a.range->empty()) ||
00123                 (b.range && b.range->empty());
00124         }
00125 
00126         inline Range* operator -> (void) const
00127         {
00128             return range;
00129         }
00130     } range;
00131 
00132     // initialization from a valid range
00133     inline std_input_iter_adapt(const Range& rng)
00134      : range(rng)
00135     { }
00136 
00137     // initialization an 'end' iterator from a valid range
00138     inline std_input_iter_adapt(const Range& rng, int)
00139      : range(rng, 0)
00140     { }
00141 
00142     // can be initialized only by the std range adaptor
00143     friend class std_range_adapt<Range>;
00144 
00145     // check if we can dereference the iterator
00146     inline bool is_dereferencable(void) const
00147     {
00148         return !range.at_end();
00149     }
00150 
00151     static Range& dummy_range(void);
00152 public:
00153     typedef std::input_iterator_tag iterator_category;
00154     typedef decltype(dummy_range().front()) value_type;
00155     typedef const value_type* pointer;
00156     typedef const value_type& reference;
00157     typedef size_t difference_type;
00158 
00159     inline std_input_iter_adapt(void) { }
00160 
00161     friend inline bool operator == (
00162         const std_input_iter_adapt& a,
00163         const std_input_iter_adapt& b
00164     )
00165     {
00166         return equal(a.range, b.range);
00167     }
00168 
00169     friend inline bool operator != (
00170         const std_input_iter_adapt& a,
00171         const std_input_iter_adapt& b
00172     )
00173     {
00174         return !equal(a.range, b.range);
00175     }
00176 
00177     inline auto operator * (void) -> decltype(range->front())
00178     {
00179         assert(is_dereferencable());
00180         return range->front();
00181     }
00182 
00183     inline void operator ++ (void)
00184     {
00185         assert(is_dereferencable());
00186         range->step_front();
00187     }
00188 
00189     inline auto operator ++ (int) -> std_range_iter_deref<
00190         Range,
00191         decltype(range->front())
00192     >
00193     {
00194         assert(is_dereferencable());
00195         std_range_iter_deref<
00196             Range,
00197             decltype(range->front())
00198         > result(range->front());
00199         range->step_front();
00200         return result;
00201     }
00202 };
00203 
00204 template <class Range>
00205 class std_range_adapt
00206 {
00207 private:
00208     Range range;
00209 public:
00210     inline std_range_adapt(const Range& rng)
00211      : range(rng)
00212     { }
00213 
00214     typedef std_input_iter_adapt<Range> const_iterator;
00215 
00216     inline const_iterator begin(void) const
00217     {
00218         return const_iterator(range);
00219     }
00220 
00221     inline const_iterator end(void) const
00222     {
00223         return const_iterator(range, 0);
00224     }
00225 };
00226 
00227 template <class MetaObject>
00228 class std_range_adapt<range<MetaObject> >
00229 {
00230 private:
00231     typedef range<MetaObject> Range;
00232     Range mo_range;
00233 public:
00234     inline std_range_adapt(const Range& rng)
00235      : mo_range(rng)
00236     { }
00237 
00238     typedef typename Range::iterator iterator;
00239 
00240     inline iterator begin(void) const
00241     {
00242         return mo_range.current;
00243     }
00244 
00245     inline iterator end(void) const
00246     {
00247         return mo_range.end;
00248     }
00249 };
00250 
00251 } // namespace aux
00252 
00253 #ifdef MIRROR_DOCUMENTATION_ONLY
00254 
00255 
00263 template <class Range> StdRange make_std_range(Range range);
00264 #else
00265 template <class Range>
00266 inline aux::std_range_adapt<Range> make_std_range(Range range)
00267 {
00268     return aux::std_range_adapt<Range>(range);
00269 }
00270 #endif
00271 
00272 LAGOON_NAMESPACE_END
00273 
00274 #endif //include guard
00275 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.