]>
Commit | Line | Data |
---|---|---|
e1ae0531 DK |
1 | #ifndef APT_HELPER_TEESTREAM_H |
2 | #define APT_HELPER_TEESTREAM_H | |
3 | ||
4 | /* 'basic' implementation of a streambuf which passes the output | |
5 | to two 'real' streambufs emulating '| tee' on the shell | |
6 | ||
7 | The main use is streaming debug output to std::clog as well as | |
8 | a logfile easily, so don't expect that to be a bulletproof | |
9 | implementation. */ | |
10 | ||
11 | #include <iostream> | |
12 | #include <apt-pkg/macros.h> | |
13 | ||
14 | template <typename CharT, typename Traits = std::char_traits<CharT> | |
15 | > class basic_teebuf: public std::basic_streambuf<CharT, Traits> | |
16 | { | |
17 | public: | |
18 | basic_teebuf(std::basic_streambuf<CharT, Traits> * const sb1, | |
19 | std::basic_streambuf<CharT, Traits> * const sb2) | |
20 | : s1(sb1), s2(sb2) {} | |
21 | protected: | |
22 | virtual std::streamsize xsputn(const CharT* s, std::streamsize c) APT_OVERRIDE | |
23 | { | |
24 | return s2->sputn(s, s1->sputn(s, c)); | |
25 | } | |
26 | // overflow is the fallback of sputc which is non-virtual | |
27 | typedef typename Traits::int_type int_type; | |
28 | virtual int_type overflow(int_type ch = Traits::eof()) APT_OVERRIDE | |
29 | { | |
30 | auto const eof = Traits::eof(); | |
31 | if (Traits::eq_int_type(ch, Traits::eof()) == true) | |
32 | return eof; | |
33 | ||
34 | auto const r1 = s1->sputc(Traits::to_char_type(ch)); | |
35 | auto const r2 = s2->sputc(Traits::to_char_type(ch)); | |
36 | return Traits::eq_int_type(r1, eof) ? r1: r2; | |
37 | } | |
38 | virtual void imbue(const std::locale& loc) APT_OVERRIDE | |
39 | { | |
40 | s1->pubimbue(loc); | |
41 | s2->pubimbue(loc); | |
42 | } | |
43 | virtual int sync() APT_OVERRIDE | |
44 | { | |
45 | auto const r1 = s1->pubsync(); | |
46 | auto const r2 = s2->pubsync(); | |
47 | return r1 == 0 ? r2 : r1; | |
48 | } | |
49 | private: | |
50 | std::basic_streambuf<CharT, Traits> * const s1; | |
51 | std::basic_streambuf<CharT, Traits> * const s2; | |
52 | }; | |
53 | template <typename CharT, typename Traits = std::char_traits<CharT> | |
54 | > class basic_teeostream: public std::basic_ostream<CharT, Traits> | |
55 | { | |
56 | public: | |
57 | basic_teeostream(std::basic_ostream<CharT, Traits> &o1, std::basic_ostream<CharT, Traits> &o2) : | |
58 | std::basic_ostream<CharT, Traits>(&tbuf), tbuf(o1.rdbuf(), o2.rdbuf()) {} | |
59 | private: | |
60 | basic_teebuf<CharT, Traits> tbuf; | |
61 | }; | |
62 | #endif |