Mirror reflection library - Lagoon run-time layer 0.5.13
|
00001 00010 #ifndef LAGOON_RANGE_CHAIN_1011291729_HPP 00011 #define LAGOON_RANGE_CHAIN_1011291729_HPP 00012 00013 #include <lagoon/range/utils.hpp> 00014 #include <cassert> 00015 00016 LAGOON_NAMESPACE_BEGIN 00017 00018 namespace aux { 00019 00020 // Helper class containing one of the chained ranges 00021 template <size_t Index, class Range> 00022 struct chained_unit 00023 { 00024 Range range; 00025 00026 chained_unit(const Range& rng) 00027 : range(rng) 00028 { } 00029 }; 00030 00031 // Tree composing the individual units of a chained range 00032 template <size_t RootIndex, class ValueType, class ... Ranges> 00033 struct chained_unit_tree; 00034 00035 // Leaf of a chain unit tree 00036 template <size_t RootIndex, class ValueType, class Range> 00037 struct chained_unit_tree<RootIndex, ValueType, Range> 00038 : chained_unit<RootIndex, Range> 00039 { 00040 enum {unit_count = RootIndex + 1}; 00041 typedef chained_unit<RootIndex, Range> leaf; 00042 00043 chained_unit_tree(const Range& rng) 00044 : leaf(rng) 00045 { } 00046 00047 bool empty(size_t current) const 00048 { 00049 assert(current >= RootIndex); 00050 return leaf::range.empty(); 00051 } 00052 00053 void skip_empty(size_t& current) 00054 { 00055 assert(current >= RootIndex); 00056 // since this is the last one 00057 // we don't have to skip anything here 00058 } 00059 00060 void step_front(size_t& current) 00061 { 00062 assert(current == RootIndex); 00063 leaf::range.step_front(); 00064 if(leaf::range.empty()) ++current; 00065 } 00066 00067 ValueType front(size_t current) const 00068 { 00069 assert(current == RootIndex); 00070 return leaf::range.front(); 00071 } 00072 }; 00073 00074 // The implementation of the chained unit tree 00075 template <size_t RootIndex, class ValueType, class Range, class ... Ranges> 00076 struct chained_unit_tree<RootIndex, ValueType, Range, Ranges...> 00077 : chained_unit<RootIndex, Range> 00078 , chained_unit_tree<RootIndex + 1, ValueType, Ranges...> 00079 { 00080 typedef chained_unit<RootIndex, Range> leaf; 00081 typedef chained_unit_tree<RootIndex + 1, ValueType, Ranges...> tree; 00082 00083 chained_unit_tree( 00084 const Range& rng, 00085 const Ranges&... rngs 00086 ): leaf(rng) 00087 , tree(rngs...) 00088 { } 00089 00090 bool empty(size_t current) const 00091 { 00092 if(current == RootIndex) return leaf::range.empty(); 00093 else return tree::empty(current); 00094 } 00095 00096 void skip_empty(size_t& current) 00097 { 00098 assert(current == RootIndex); 00099 if(leaf::range.empty()) 00100 { 00101 ++current; 00102 tree::skip_empty(current); 00103 } 00104 } 00105 00106 void step_front(size_t& current) 00107 { 00108 if(current == RootIndex) 00109 { 00110 leaf::range.step_front(); 00111 if(leaf::range.empty()) 00112 { 00113 ++current; 00114 tree::skip_empty(current); 00115 } 00116 } 00117 else tree::step_front(current); 00118 } 00119 00120 ValueType front(size_t current) const 00121 { 00122 if(current == RootIndex) 00123 return leaf::range.front(); 00124 else return tree::front(current); 00125 } 00126 }; 00127 00128 template <typename ValueType, class ... Ranges> 00129 class chained 00130 : private chained_unit_tree<0, ValueType, Ranges...> 00131 , public leaping_base 00132 { 00133 private: 00134 typedef chained_unit_tree<0, ValueType, Ranges...> 00135 base_class; 00136 00137 // The current range unit to be used 00138 size_t current; 00139 public: 00141 chained(const Ranges&...rngs) 00142 : base_class(rngs...) 00143 , current(0) 00144 { 00145 base_class::skip_empty(current); 00146 } 00147 00149 bool empty(void) const 00150 { 00151 return base_class::empty(current); 00152 } 00153 00155 void step_front(void) 00156 { 00157 assert(!empty()); 00158 base_class::step_front(current); 00159 } 00160 00161 size_t leap_front(size_t leap) 00162 { 00163 return leaping_base::do_leap_front(*this, leap); 00164 } 00165 00167 ValueType front(void) const 00168 { 00169 assert(!empty()); 00170 return base_class::front(current); 00171 } 00172 }; 00173 00174 } // namespace aux 00175 00176 #ifdef MIRROR_DOCUMENTATION_ONLY 00177 00178 00190 template <typename ValueType, class ... Ranges> 00191 UnspecifiedRange<ValueType> chain(const Ranges&...ranges); 00192 00194 00205 template <typename Interface, class ... Ranges> 00206 UnspecifiedRange<shared<Interface> > chain_mo(const Ranges&...ranges); 00207 #else 00208 00209 // chain with arbitrary value type 00210 template <typename ValueType, class ... Ranges> 00211 aux::chained<ValueType, Ranges...> chain(const Ranges&...ranges) 00212 { 00213 return aux::chained<ValueType, Ranges...>(ranges...); 00214 } 00215 00216 // chain of shared meta-object ranges 00217 template <typename Interface, class ... Ranges> 00218 aux::chained<shared<Interface>, Ranges...> chain_mo(const Ranges&...ranges) 00219 { 00220 return aux::chained<shared<Interface>, Ranges...>(ranges...); 00221 } 00222 #endif 00223 00224 LAGOON_NAMESPACE_END 00225 00226 #endif //include guard 00227