File: consumer.h

package info (click to toggle)
libwibble 0.1.9
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 500 kB
  • ctags: 1,183
  • sloc: cpp: 5,760; sh: 113; makefile: 71
file content (126 lines) | stat: -rw-r--r-- 3,209 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/** -*- C++ -*-
    @file wibble/consumer.h
    @author Peter Rockai <me@mornfall.net>
*/

#include <iterator>

#include <wibble/amorph.h>
#include <wibble/range.h>
#include <wibble/cast.h>

#ifndef WIBBLE_CONSUMER_H
#define WIBBLE_CONSUMER_H

namespace wibble {

template< typename T > struct Consumer;

template< typename T >
struct ConsumerInterface
{
    typedef T InputType;
    virtual void consume( const T &a ) = 0;
    virtual void consume( Range< T > s ) = 0;
    virtual ~ConsumerInterface() {}
};

template< typename T, typename W >
struct ConsumerMorph : Morph< ConsumerMorph< T, W >, W, ConsumerInterface< T > >
{
    ConsumerMorph() {}
    ConsumerMorph( const W &w ) : Morph< ConsumerMorph, W, ConsumerInterface< T > >( w ) {}

    virtual void consume( const T &a ) {
        return this->wrapped().consume( a );
    }

    virtual void consume( Range< T > s ) {
        while ( !s.empty() ) {
            consume( s.head() );
            s = s.tail();
        }
    }
};

template< typename T, typename Self >
struct ConsumerMixin : mixin::Comparable< Self >
{
    Self &self() { return *static_cast< const Self * >( this ); }
    typedef std::output_iterator_tag iterator_category;
    typedef T ConsumedType;

    bool operator<=( const Self &o ) const { return this <= &o; }
    Consumer< T > &operator++() { return self(); }
    Consumer< T > &operator++(int) { return self(); }
    Consumer< T > &operator*() { return self(); }
    Consumer< T > &operator=( const T &a ) {
        self()->consume( a );
        return self();
    }
};

template< typename T >
struct Consumer: Amorph< Consumer< T >, ConsumerInterface< T > >,
                 ConsumerMixin< T, Consumer< T > >
{
    typedef Amorph< Consumer< T >, ConsumerInterface< T > > Super;

    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;

    Consumer( const MorphInterface< ConsumerInterface< T > > &i ) : Super( i ) {}
    Consumer() {}

    void consume( const T &a ) {
        return this->implementation()->consume( a );
    }

    Consumer< T > &operator=( const T &a ) {
        consume( a );
        return *this;
    }
    // output iterator - can't read or move
};

template< typename T, typename Out >
struct ConsumerFromIterator : ConsumerMixin< T, ConsumerFromIterator< T, Out > >
{
    ConsumerFromIterator( Out out ) : m_out( out ) {}
    void consume( const T& a ) {
        *(*m_out) = a;
        ++(*m_out);
    }
protected:
    Out m_out;
};

template< typename R >
Consumer< typename R::ConsumedType > consumerMorph( R r ) {
    return ConsumerMorph< typename R::ConsumedType , R >( r );
}

// insert iterators
template< typename Out >
Consumer< typename Out::container_type::value_type > consumer( Out out ) {
    return consumerMorph(
        ConsumerFromIterator< typename Out::container_type::value_type, Out >( out ) );
}

// containers
template< typename T >
typename IsType< Consumer< typename T::value_type >, typename T::iterator >::T consumer( T &c ) {
    return consumer( std::inserter( c, c.end() ) );
}

// consumers
template< typename T >
Consumer< T > consumer( const ConsumerInterface< T > &t ) {
    return t;
}

}

#endif