source: cppstreams/stream.h @ 3

Last change on this file since 3 was 3, checked in by gobi, 13 years ago

license

File size: 9.7 KB
Line 
1/*
2 * Copyright (c) 2011-2012, Attila Gobi and Zalan Szugyi
3 * All rights reserved.
4 *
5 * This software was developed by Attila Gobi and Zalan Szugyi.
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)
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
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.
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
42template<typename T>
43struct 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
52template<typename T>
53struct stream
54{
55protected:
56    struct impl;
57
58public:
59    typedef T value_type;
60
61    stream(const stream<T> &o)
62        : impl_(o.impl_->clone())
63    { 
64    }
65
66    stream(stream<T> &&o)
67        : impl_(0)
68    {
69        std::swap(impl_, o.impl_);
70    }
71   
72    stream<T> & operator = (stream<T> &&o)
73    {
74        if(this != &o) {
75                std::swap(impl_, o.impl_);
76                return *this;
77        }
78    }
79   
80    ~stream()
81    {
82        delete impl_;
83    }
84
85    struct iterator {
86        iterator& operator ++() 
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
112protected:
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)
130            : a_(a), s_(std::forward<ST>(s)) 
131        { }
132
133        const T &get(const iterator &) 
134        {
135            return a_;
136        }
137
138        void next(iterator &it)
139        {
140            it.impl_ = const_cast<impl**>(&s_.impl_);
141        }
142
143        impl *clone() 
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)
162        { 
163            *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1), stream<T>(this));
164            ++it1;
165            return *it;
166        }
167
168        void next(iterator &it) 
169        {
170            *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1), stream<T>(this));
171            ++it1;
172            ++it;
173        }
174
175        impl *clone() 
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_;
183        };
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
191        const T &get(const iterator &it) 
192        {
193            impl *x = new mapimpl2<Op, ST>(op_, std::forward<ST>(s_));
194            *(it.impl_) = x;
195           
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
208        impl *clone() 
209        {
210            return new mapimpl<Op, ST>(op_, std::forward<ST>(s_));
211        }
212
213    private:
214        typename storage_type<ST>::type s_;
215                Op op_;
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
225        const T &get(const iterator &it) 
226        { 
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
233        void next(iterator &it) 
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
241        impl *clone() 
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)
261        { 
262            *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1, *it2), stream<T>(this));
263            ++it1;
264            ++it2;
265            return *it;
266        }
267
268        void next(iterator &it) 
269        {
270            *(it.impl_)=new addimpl<stream<T>&&>(op_(*it1, *it2), stream<T>(this));
271            ++it1;
272            ++it2;
273            ++it;
274        }
275
276        impl *clone() 
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
287public:
288        template <typename S, typename U>
289        friend stream<U> operator <<= (const U& a, S && s);
290   
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    }
296   
297        template <typename ST1, typename Op>
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
303        static stream<T> pure(const T& v)
304        {
305                stream<T> s = v<<=s;
306                return s;
307        }
308};
309
310template<typename ST>
311struct stream_value_type
312{
313        typedef typename std::remove_reference<ST>::type::value_type type;
314};
315
316template <typename S, typename U=typename stream_value_type<S>::type>
317stream<U> operator <<= (const U& a, S && s)
318{
319        return stream<U>(new typename stream<U>::template addimpl<decltype(s)>(a, std::forward<S>(s)));
320}
321   
322template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type>
323stream<T> operator +(ST1 &&s1, ST2 &&s2)
324{
325        return stream<T>::zipwith(std::plus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2));
326}
327
328template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type>
329stream<T> operator -(ST1 &&s1, ST2 &&s2)
330{
331        return stream<T>::zipwith(std::minus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2));
332}
333
334template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type>
335stream<T> operator *(ST1 &&s1, ST2 &&s2)
336{
337        return stream<T>::zipwith(std::multiplies<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2));
338}
339
340template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type>
341stream<T> operator /(ST1 &&s1, ST2 &&s2)
342{
343        return stream<T>::zipwith(std::divides<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2));
344}
345
346template<typename ST1, typename ST2, typename T=typename stream_value_type<ST1>::type>
347stream<T> operator %(ST1 &&s1, ST2 &&s2)
348{
349        return stream<T>::zipwith(std::modulus<T>(), std::forward<ST1>(s1), std::forward<ST2>(s2));
350}
351
352template<typename ST, typename T=typename stream_value_type<ST>::type>
353stream<T> operator -(ST &&s)
354{
355        return stream<T>::map(std::negate<T>(), std::forward<ST>(s));
356}
357
358#ifdef HAVE_LITERALS
359
360struct stream_proxy
361{
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;
369};
370
371stream_proxy operator "" _s (unsigned long long i)
372{
373        return stream_proxy(i);
374}
375
376#endif//HAVE_LITERALS
377
378#endif//__stream_h__
Note: See TracBrowser for help on using the repository browser.