[2] | 1 | /* |
---|
[3] | 2 | * Copyright (c) 2011-2012, Attila Gobi and Zalan Szugyi |
---|
| 3 | * All rights reserved. |
---|
[2] | 4 | * |
---|
[16] | 5 | * This software was developed by Attila Gobi and Zalan Szugyi. |
---|
[3] | 6 | * The project was supported by the European Union and co-financed by the |
---|
| 7 | * European Social Fund (grant agreement no. TAMOP 4.2.1./B-09/1/KMR-2010-0003) |
---|
[2] | 8 | * |
---|
[3] | 9 | * Redistribution and use in source and binary forms, with or without |
---|
| 10 | * modification, are permitted provided that the following conditions are met: |
---|
[16] | 11 | * 1. Redistributions of source code must retain the above copyright |
---|
[3] | 12 | * notice, this list of conditions and the following disclaimer. |
---|
[16] | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
[3] | 14 | * notice, this list of conditions and the following disclaimer in the |
---|
| 15 | * documentation and/or other materials provided with the distribution. |
---|
[2] | 16 | * |
---|
[3] | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS "AS IS" AND ANY |
---|
| 18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
---|
| 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
---|
| 20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
---|
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
---|
| 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
---|
| 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
---|
| 25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
---|
| 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
[2] | 27 | */ |
---|
| 28 | |
---|
| 29 | #ifndef __stream_h__ |
---|
| 30 | #define __stream_h__ |
---|
| 31 | |
---|
| 32 | #include <iostream> |
---|
| 33 | #include <utility> |
---|
| 34 | #include <ctime> |
---|
| 35 | #include <cassert> |
---|
| 36 | |
---|
| 37 | #if __GNUC__ > 4 || \ |
---|
| 38 | (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) |
---|
| 39 | #define HAVE_LITERALS |
---|
| 40 | #endif |
---|
| 41 | |
---|
| 42 | template<typename T> |
---|
| 43 | struct storage_type |
---|
| 44 | { |
---|
| 45 | typedef typename std::conditional< |
---|
| 46 | std::is_lvalue_reference<typename std::remove_const<T>::type>::value, |
---|
| 47 | typename std::remove_const<T>::type, |
---|
| 48 | typename std::remove_reference<typename std::remove_const<T>::type>::type |
---|
| 49 | >::type type; |
---|
| 50 | }; |
---|
| 51 | |
---|
| 52 | template<typename T> |
---|
| 53 | struct stream |
---|
| 54 | { |
---|
| 55 | protected: |
---|
| 56 | struct impl; |
---|
| 57 | |
---|
| 58 | public: |
---|
| 59 | typedef T value_type; |
---|
| 60 | |
---|
| 61 | stream(const stream<T> &o) |
---|
| 62 | : impl_(o.impl_->clone()) |
---|
[16] | 63 | { |
---|
[2] | 64 | } |
---|
| 65 | |
---|
| 66 | stream(stream<T> &&o) |
---|
| 67 | : impl_(0) |
---|
| 68 | { |
---|
| 69 | std::swap(impl_, o.impl_); |
---|
| 70 | } |
---|
[16] | 71 | |
---|
[2] | 72 | stream<T> & operator = (stream<T> &&o) |
---|
| 73 | { |
---|
[16] | 74 | if(this != &o) { |
---|
| 75 | std::swap(impl_, o.impl_); |
---|
| 76 | return *this; |
---|
| 77 | } |
---|
[2] | 78 | } |
---|
[16] | 79 | |
---|
[2] | 80 | ~stream() |
---|
| 81 | { |
---|
| 82 | delete impl_; |
---|
| 83 | } |
---|
| 84 | |
---|
| 85 | struct iterator { |
---|
[16] | 86 | iterator& operator ++() |
---|
[2] | 87 | { |
---|
| 88 | (*impl_)->next(*this); |
---|
| 89 | return *this; |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | const T& operator *() const |
---|
| 93 | { |
---|
| 94 | return (*impl_)->get(*this); |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | friend class stream<T>; |
---|
| 98 | |
---|
| 99 | protected: |
---|
| 100 | iterator(impl ** impl) |
---|
| 101 | :impl_(impl) |
---|
| 102 | { } |
---|
| 103 | |
---|
| 104 | impl **impl_; |
---|
| 105 | }; |
---|
| 106 | |
---|
| 107 | iterator begin() const |
---|
| 108 | { |
---|
| 109 | return iterator(&impl_); |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | protected: |
---|
| 113 | |
---|
| 114 | struct impl { |
---|
| 115 | virtual ~impl() {} |
---|
| 116 | virtual const T &get(const iterator &) = 0; |
---|
| 117 | virtual void next(iterator &) = 0; |
---|
| 118 | virtual impl* clone() = 0; |
---|
| 119 | }; |
---|
| 120 | |
---|
| 121 | mutable impl * impl_; |
---|
| 122 | |
---|
| 123 | stream(impl *i) |
---|
| 124 | :impl_(i) |
---|
| 125 | { } |
---|
| 126 | |
---|
| 127 | template<typename ST> |
---|
| 128 | struct addimpl: public impl { |
---|
| 129 | addimpl(const T &a, ST &&s) |
---|
[16] | 130 | : a_(a), s_(std::forward<ST>(s)) |
---|
[2] | 131 | { } |
---|
| 132 | |
---|
[16] | 133 | const T &get(const iterator &) |
---|
[2] | 134 | { |
---|
| 135 | return a_; |
---|
| 136 | } |
---|
| 137 | |
---|
| 138 | void next(iterator &it) |
---|
| 139 | { |
---|
| 140 | it.impl_ = const_cast<impl**>(&s_.impl_); |
---|
| 141 | } |
---|
| 142 | |
---|
[16] | 143 | impl *clone() |
---|
[2] | 144 | { |
---|
| 145 | return new addimpl<ST>(a_, std::forward<ST>(s_)); |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | private: |
---|
| 149 | const T a_; |
---|
| 150 | typename storage_type<ST>::type s_; |
---|
| 151 | }; |
---|
| 152 | |
---|
| 153 | template<typename Op, typename ST> |
---|
| 154 | struct mapimpl2: public impl { |
---|
| 155 | mapimpl2(Op op, ST &&s) |
---|
| 156 | :s_(std::forward<ST>(s)), |
---|
| 157 | it1(s_.begin()), op_(op) |
---|
| 158 | { |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | const T &get(const iterator &it) |
---|
[16] | 162 | { |
---|
[2] | 163 | *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1), stream<T>(this)); |
---|
| 164 | ++it1; |
---|
| 165 | return *it; |
---|
| 166 | } |
---|
| 167 | |
---|
[16] | 168 | void next(iterator &it) |
---|
[2] | 169 | { |
---|
| 170 | *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1), stream<T>(this)); |
---|
| 171 | ++it1; |
---|
| 172 | ++it; |
---|
| 173 | } |
---|
| 174 | |
---|
[16] | 175 | impl *clone() |
---|
[2] | 176 | { |
---|
| 177 | return new mapimpl2<Op, ST>(op_, std::forward<ST>(s_)); |
---|
| 178 | } |
---|
| 179 | private: |
---|
| 180 | typename storage_type<ST>::type s_; |
---|
| 181 | iterator it1; |
---|
| 182 | Op op_; |
---|
[16] | 183 | }; |
---|
[2] | 184 | |
---|
| 185 | template<typename Op, typename ST> |
---|
| 186 | struct mapimpl: public impl { |
---|
| 187 | mapimpl(Op op, ST &&s) |
---|
| 188 | : s_(std::forward<ST>(s)), op_(op) |
---|
| 189 | { } |
---|
| 190 | |
---|
[16] | 191 | const T &get(const iterator &it) |
---|
[2] | 192 | { |
---|
| 193 | impl *x = new mapimpl2<Op, ST>(op_, std::forward<ST>(s_)); |
---|
| 194 | *(it.impl_) = x; |
---|
[16] | 195 | |
---|
[2] | 196 | delete this; |
---|
| 197 | return *it; |
---|
| 198 | } |
---|
| 199 | |
---|
| 200 | void next(iterator &it) |
---|
| 201 | { |
---|
| 202 | impl *x = new mapimpl2<Op, ST>(op_, std::forward<ST>(s_)); |
---|
| 203 | *(it.impl_) = x; |
---|
| 204 | delete this; |
---|
| 205 | ++it; |
---|
| 206 | } |
---|
| 207 | |
---|
[16] | 208 | impl *clone() |
---|
[2] | 209 | { |
---|
| 210 | return new mapimpl<Op, ST>(op_, std::forward<ST>(s_)); |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | private: |
---|
| 214 | typename storage_type<ST>::type s_; |
---|
[16] | 215 | Op op_; |
---|
[2] | 216 | }; |
---|
| 217 | |
---|
| 218 | template<typename Op, typename ST1, typename ST2> |
---|
| 219 | struct zipimpl: public impl |
---|
| 220 | { |
---|
| 221 | zipimpl(Op op, ST1 &&s1, ST2 &&s2) |
---|
| 222 | :s1_(std::forward<ST1>(s1)), s2_(std::forward<ST2>(s2)), op_(op) |
---|
| 223 | { } |
---|
| 224 | |
---|
[16] | 225 | const T &get(const iterator &it) |
---|
| 226 | { |
---|
[2] | 227 | impl *x = new zipimpl2<Op, ST1, ST2>(op_, std::forward<ST1>(s1_), std::forward<ST2>(s2_)); |
---|
| 228 | *(it.impl_) = x; |
---|
| 229 | delete this; |
---|
| 230 | return *it; |
---|
| 231 | } |
---|
| 232 | |
---|
[16] | 233 | void next(iterator &it) |
---|
[2] | 234 | { |
---|
| 235 | impl *x = new zipimpl2<Op, ST1, ST2>(op_, std::forward<ST1>(s1_), std::forward<ST2>(s2_)); |
---|
| 236 | *(it.impl_) = x; |
---|
| 237 | delete this; |
---|
| 238 | ++it; |
---|
| 239 | } |
---|
| 240 | |
---|
[16] | 241 | impl *clone() |
---|
[2] | 242 | { |
---|
| 243 | return new zipimpl<Op, ST1, ST2>(op_, std::forward<ST1>(s1_), std::forward<ST2>(s2_)); |
---|
| 244 | } |
---|
| 245 | private: |
---|
| 246 | typename storage_type<ST1>::type s1_; |
---|
| 247 | typename storage_type<ST2>::type s2_; |
---|
| 248 | Op op_; |
---|
| 249 | }; |
---|
| 250 | |
---|
| 251 | template<typename Op, typename ST1, typename ST2> |
---|
| 252 | struct zipimpl2: public impl |
---|
| 253 | { |
---|
| 254 | zipimpl2(Op op, ST1 &&s1, ST2 &&s2) |
---|
| 255 | :s1_(std::forward<ST1>(s1)),s2_(std::forward<ST2>(s2)), |
---|
| 256 | it1(s1_.begin()), it2(s2_.begin()), op_(op) |
---|
| 257 | { |
---|
| 258 | } |
---|
| 259 | |
---|
| 260 | const T &get(const iterator &it) |
---|
[16] | 261 | { |
---|
[2] | 262 | *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1, *it2), stream<T>(this)); |
---|
| 263 | ++it1; |
---|
| 264 | ++it2; |
---|
| 265 | return *it; |
---|
| 266 | } |
---|
| 267 | |
---|
[16] | 268 | void next(iterator &it) |
---|
[2] | 269 | { |
---|
| 270 | *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1, *it2), stream<T>(this)); |
---|
| 271 | ++it1; |
---|
| 272 | ++it2; |
---|
| 273 | ++it; |
---|
| 274 | } |
---|
| 275 | |
---|
[16] | 276 | impl *clone() |
---|
[2] | 277 | { |
---|
| 278 | return new zipimpl2<Op, ST1, ST2>(op_, std::forward<ST1>(s1_), std::forward<ST2>(s2_)); |
---|
| 279 | } |
---|
| 280 | private: |
---|
| 281 | typename storage_type<ST1>::type s1_; |
---|
| 282 | typename storage_type<ST2>::type s2_; |
---|
| 283 | iterator it1, it2; |
---|
| 284 | Op op_; |
---|
| 285 | }; |
---|
| 286 | |
---|
| 287 | public: |
---|
[16] | 288 | template <typename S, typename U> |
---|
| 289 | friend stream<U> operator <<= (const U& a, S && s); |
---|
| 290 | |
---|
[2] | 291 | template <typename Op, typename ST1, typename ST2> |
---|
| 292 | static stream<T> zipwith(Op op, ST1 &&s1, ST2 &&s2) |
---|
| 293 | { |
---|
| 294 | return stream(new zipimpl<Op, decltype(s1), decltype(s2)>(op, std::forward<ST1>(s1), std::forward<ST2>(s2))); |
---|
| 295 | } |
---|
[16] | 296 | |
---|
| 297 | template <typename ST1, typename Op> |
---|
[2] | 298 | static stream<T> map(Op op, ST1 &&s1) |
---|
| 299 | { |
---|
| 300 | return stream(new mapimpl<Op, decltype(s1)>(op, std::forward<ST1>(s1))); |
---|
| 301 | } |
---|
| 302 | |
---|
[16] | 303 | static stream<T> pure(const T& v) |
---|
| 304 | { |
---|
| 305 | stream<T> s = v<<=s; |
---|
| 306 | return s; |
---|
| 307 | } |
---|
[2] | 308 | }; |
---|
| 309 | |
---|
| 310 | template<typename ST> |
---|
| 311 | struct stream_value_type |
---|
| 312 | { |
---|
[16] | 313 | typedef typename std::remove_reference<ST>::type::value_type type; |
---|
[2] | 314 | }; |
---|
| 315 | |
---|
| 316 | template <typename S, typename U=typename stream_value_type<S>::type> |
---|
| 317 | stream<U> operator <<= (const U& a, S && s) |
---|
| 318 | { |
---|
[16] | 319 | return stream<U>(new typename stream<U>::template addimpl<decltype(s)>(a, std::forward<S>(s))); |
---|
[2] | 320 | } |
---|
[16] | 321 | |
---|
[2] | 322 | template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type> |
---|
| 323 | stream<T> operator +(ST1 &&s1, ST2 &&s2) |
---|
| 324 | { |
---|
[16] | 325 | return stream<T>::zipwith(std::plus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2)); |
---|
[2] | 326 | } |
---|
| 327 | |
---|
| 328 | template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type> |
---|
| 329 | stream<T> operator -(ST1 &&s1, ST2 &&s2) |
---|
| 330 | { |
---|
[16] | 331 | return stream<T>::zipwith(std::minus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2)); |
---|
[2] | 332 | } |
---|
| 333 | |
---|
| 334 | template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type> |
---|
| 335 | stream<T> operator *(ST1 &&s1, ST2 &&s2) |
---|
| 336 | { |
---|
[16] | 337 | return stream<T>::zipwith(std::multiplies<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2)); |
---|
[2] | 338 | } |
---|
| 339 | |
---|
| 340 | template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type> |
---|
| 341 | stream<T> operator /(ST1 &&s1, ST2 &&s2) |
---|
| 342 | { |
---|
[16] | 343 | return stream<T>::zipwith(std::divides<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2)); |
---|
[2] | 344 | } |
---|
| 345 | |
---|
| 346 | template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type> |
---|
| 347 | stream<T> operator %(ST1 &&s1, ST2 &&s2) |
---|
| 348 | { |
---|
[16] | 349 | return stream<T>::zipwith(std::modulus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2)); |
---|
[2] | 350 | } |
---|
| 351 | |
---|
| 352 | template<typename ST, typename T=typename stream_value_type<ST>::type> |
---|
| 353 | stream<T> operator -(ST &&s) |
---|
| 354 | { |
---|
[16] | 355 | return stream<T>::map(std::negate<T>(), std::forward<ST>(s)); |
---|
[2] | 356 | } |
---|
| 357 | |
---|
| 358 | #ifdef HAVE_LITERALS |
---|
| 359 | |
---|
| 360 | struct stream_proxy |
---|
| 361 | { |
---|
[16] | 362 | stream_proxy(unsigned long long i): x(i) {} |
---|
| 363 | template <typename T> |
---|
| 364 | operator stream<T> () { |
---|
| 365 | stream<T> a = static_cast<T>(x)<<=a; |
---|
| 366 | return a; |
---|
| 367 | } |
---|
| 368 | unsigned long long x; |
---|
[2] | 369 | }; |
---|
| 370 | |
---|
| 371 | stream_proxy operator "" _s (unsigned long long i) |
---|
| 372 | { |
---|
[16] | 373 | return stream_proxy(i); |
---|
[2] | 374 | } |
---|
| 375 | |
---|
| 376 | #endif//HAVE_LITERALS |
---|
| 377 | |
---|
| 378 | #endif//__stream_h__ |
---|