Mirror reflection library - Lagoon run-time layer 0.5.13
|
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