Rewrite BufferedFile as a standalone class
[libs/core.git] / source / io / filtered.h
1 #ifndef MSP_IO_FILTERED_H_
2 #define MSP_IO_FILTERED_H_
3
4 namespace Msp {
5 namespace IO {
6
7 /**
8 This class is broken by design.  Do not use.  It exposes base class methods in
9 an unsafe and misleading way.  In particular, a Filtered<File, Buffered> causes
10 seeks to behave incorrectly.
11 */
12 template<typename B, typename F>
13 class Filtered: public B
14 {
15 private:
16         struct Activator
17         {
18                 Filtered &f;
19
20                 Activator(Filtered &f_): f(f_) { f.active = true; }
21                 ~Activator() { f.active = false; }
22         };
23
24         F filter;
25         bool active;
26
27 public:
28         Filtered(): filter(*this), active(false) { }
29         ~Filtered() { active = true; }
30
31         template<typename A0>
32         Filtered(A0 a0): B(a0), filter(*this), active(false) { }
33
34         template<typename A0, typename A1>
35         Filtered(A0 a0, A1 a1): B(a0, a1), filter(*this), active(false) { }
36
37 protected:
38         virtual unsigned do_write(const char *b, unsigned s)
39         {
40                 if(!active)
41                 {
42                         Activator a(*this);
43                         return filter.write(b, s);
44                 }
45                 else
46                         return B::do_write(b, s);
47         }
48
49         virtual unsigned do_read(char *b, unsigned s)
50         {
51                 if(!active)
52                 {
53                         Activator a(*this);
54                         return filter.read(b, s);
55                 }
56                 else
57                         return B::do_read(b, s);
58         }
59
60 public:
61         virtual unsigned put(char c)
62         {
63                 if(active)
64                         return B::put(c);
65
66                 Activator a(*this);
67                 return filter.put(c);
68         }
69
70         virtual bool getline(std::string &l)
71         {
72                 if(active)
73                         return B::getline(l);
74
75                 Activator a(*this);
76                 return filter.getline(l);
77         }
78
79         virtual int get()
80         {
81                 if(active)
82                         return B::get();
83                         
84                 Activator a(*this);
85                 return filter.get();
86         }
87
88         F &get_filter() { return filter; }
89 };
90
91 } // namespace IO
92 } // namespace Msp
93
94 #endif