forked from psi46/psi46test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
datapipe.h
102 lines (74 loc) · 2.38 KB
/
datapipe.h
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
// connect.h
#ifndef CONNECT_H
#define CONNECT_H
#include <stdexcept>
// === data pipe error ======================================================
// error class generator
#define DATAPIPE_ERROR(name, message) \
class name : public DataPipeException \
{ public: name() : DataPipeException(message) {}; };
// base class for all data pipe errors
class DataPipeException : public std::runtime_error
{
public:
DataPipeException(const char *message) : std::runtime_error(message) {};
};
DATAPIPE_ERROR(DP_not_connected, "Not connected")
// === data source ==========================================================
// The inheritor must define ReadLast and Read
template <class T>
class CSource
{
virtual T ReadLast() = 0;
virtual T Read() = 0;
public:
virtual ~CSource() {}
template <class S> friend class CSink;
};
// Null source for not connected sinks
template <class T>
class CNullSource : public CSource<T>
{
protected:
CNullSource() {}
CNullSource(const CNullSource&) {}
~CNullSource() {}
T ReadLast() { throw DP_not_connected(); }
T Read() { return ReadLast(); }
template <class TO> friend class CSink;
};
// === data sink ============================================================
template <class TI, class TO> class CDataPipe;
template <class T>
class CSink
{
protected:
CSource<T> *src;
static CNullSource<T> null;
public:
CSink() : src(&null) {}
T GetLast() { return src->ReadLast(); }
T Get() { return src->Read(); }
void GetAll() { while (true) Get(); }
template <class TI, class TO> friend void operator >> (CSource<TI> &, CSink<TO> &);
template <class TI, class TO> friend CSource<TO>& operator >> (CSource<TI> &in, CDataPipe<TI,TO> &out);
};
template <class T> CNullSource<T> CSink<T>::null;
// === data in -> out (pipe) ================================================
template <class TI, class TO=TI>
class CDataPipe : public CSink<TI>, public CSource<TO> {};
// === operators to connect pipes ===========================================
// source -> sink; source -> datapipe
template <class TI, class TO>
void operator >> (CSource<TI> &in, CSink<TO> &out)
{
out.src = ∈
}
// source -> datapipe -> datapipe -> sink
template <class TI, class TO>
CSource<TO>& operator >> (CSource<TI> &in, CDataPipe<TI,TO> &out)
{
out.src = ∈
return out;
}
#endif