]> git.saurik.com Git - apt.git/blob - test/interactive-helper/teestream.h
The entire concept of PendingError() is flawed :/.
[apt.git] / test / interactive-helper / teestream.h
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